mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Fixed a ICE on calldata to struct member copy
This commit is contained in:
parent
ef8911a629
commit
0fe5811459
@ -18,6 +18,7 @@ Bugfixes:
|
|||||||
* Immutables: Fix wrong error when the constructor of a base contract uses ``return`` and the parent contract contains immutable variables.
|
* Immutables: Fix wrong error when the constructor of a base contract uses ``return`` and the parent contract contains immutable variables.
|
||||||
* IR Generator: Add missing cleanup during the conversion of fixed bytes types to smaller fixed bytes types.
|
* IR Generator: Add missing cleanup during the conversion of fixed bytes types to smaller fixed bytes types.
|
||||||
* IR Generator: Add missing cleanup for indexed event arguments of value type.
|
* IR Generator: Add missing cleanup for indexed event arguments of value type.
|
||||||
|
* IR Generator: Fix internal error when copying reference types in calldata and storage to struct or array members in memory.
|
||||||
* IR Generator: Fix IR syntax error when copying storage arrays of structs containing functions.
|
* IR Generator: Fix IR syntax error when copying storage arrays of structs containing functions.
|
||||||
* Natspec: Fix ICE when overriding a struct getter with a Natspec-documented return value and the name in the struct is different.
|
* Natspec: Fix ICE when overriding a struct getter with a Natspec-documented return value and the name in the struct is different.
|
||||||
* TypeChecker: Fix ICE when a constant variable declaration forward references a struct.
|
* TypeChecker: Fix ICE when a constant variable declaration forward references a struct.
|
||||||
|
@ -2985,8 +2985,11 @@ void IRGeneratorForStatements::writeToLValue(IRLValue const& _lvalue, IRVariable
|
|||||||
{
|
{
|
||||||
solAssert(_lvalue.type.sizeOnStack() == 1);
|
solAssert(_lvalue.type.sizeOnStack() == 1);
|
||||||
auto const* valueReferenceType = dynamic_cast<ReferenceType const*>(&_value.type());
|
auto const* valueReferenceType = dynamic_cast<ReferenceType const*>(&_value.type());
|
||||||
solAssert(valueReferenceType && valueReferenceType->dataStoredIn(DataLocation::Memory));
|
solAssert(valueReferenceType);
|
||||||
appendCode() << "mstore(" + _memory.address + ", " + _value.part("mpos").name() + ")\n";
|
if (valueReferenceType->dataStoredIn(DataLocation::Memory))
|
||||||
|
appendCode() << "mstore(" + _memory.address + ", " + _value.part("mpos").name() + ")\n";
|
||||||
|
else
|
||||||
|
appendCode() << "mstore(" + _memory.address + ", " + m_utils.conversionFunction(_value.type(), _lvalue.type) + "(" + _value.commaSeparatedList() + "))\n";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[&](IRLValue::Stack const& _stack) { assign(_stack.variable, _value); },
|
[&](IRLValue::Stack const& _stack) { assign(_stack.variable, _value); },
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
// Example from https://github.com/ethereum/solidity/issues/12558
|
||||||
|
pragma abicoder v2;
|
||||||
|
contract C {
|
||||||
|
function f(uint[] calldata a) external returns (uint[][] memory) {
|
||||||
|
uint[][] memory m = new uint[][](2);
|
||||||
|
m[0] = a;
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contract Test {
|
||||||
|
C immutable c = new C();
|
||||||
|
|
||||||
|
function test() external returns (bool) {
|
||||||
|
uint[] memory arr = new uint[](4);
|
||||||
|
|
||||||
|
arr[0] = 13;
|
||||||
|
arr[1] = 14;
|
||||||
|
arr[2] = 15;
|
||||||
|
arr[3] = 16;
|
||||||
|
|
||||||
|
uint[][] memory ret = c.f(arr);
|
||||||
|
assert(ret.length == 2);
|
||||||
|
assert(ret[0].length == 4);
|
||||||
|
assert(ret[0][0] == 13);
|
||||||
|
assert(ret[0][1] == 14);
|
||||||
|
assert(ret[0][2] == 15);
|
||||||
|
assert(ret[0][3] == 16);
|
||||||
|
assert(ret[1].length == 0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >homestead
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// test() -> true
|
24
test/libsolidity/semanticTests/structs/copy_from_storage.sol
Normal file
24
test/libsolidity/semanticTests/structs/copy_from_storage.sol
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
pragma abicoder v2;
|
||||||
|
// Example from https://github.com/ethereum/solidity/issues/12558
|
||||||
|
struct S {
|
||||||
|
uint x;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract C {
|
||||||
|
S sStorage;
|
||||||
|
constructor() {
|
||||||
|
sStorage.x = 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
function f() external returns (S[] memory) {
|
||||||
|
S[] memory sMemory = new S[](1);
|
||||||
|
|
||||||
|
sMemory[0] = sStorage;
|
||||||
|
|
||||||
|
return sMemory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f() -> 0x20, 1, 13
|
@ -0,0 +1,96 @@
|
|||||||
|
pragma abicoder v2;
|
||||||
|
|
||||||
|
struct S { uint value; }
|
||||||
|
|
||||||
|
contract Test {
|
||||||
|
S[][] a;
|
||||||
|
S[] b;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
a.push();
|
||||||
|
a[0].push(S(1));
|
||||||
|
a[0].push(S(2));
|
||||||
|
a[0].push(S(3));
|
||||||
|
|
||||||
|
b.push(S(4));
|
||||||
|
b.push(S(5));
|
||||||
|
b.push(S(6));
|
||||||
|
b.push(S(7));
|
||||||
|
}
|
||||||
|
|
||||||
|
function test1() external returns (bool) {
|
||||||
|
a.push();
|
||||||
|
a[1] = b;
|
||||||
|
|
||||||
|
assert(a.length == 2);
|
||||||
|
assert(a[0].length == 3);
|
||||||
|
assert(a[1].length == 4);
|
||||||
|
assert(a[1][0].value == 4);
|
||||||
|
assert(a[1][1].value == 5);
|
||||||
|
assert(a[1][2].value == 6);
|
||||||
|
assert(a[1][3].value == 7);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test2() external returns (bool) {
|
||||||
|
S[][] memory temp = new S[][](2);
|
||||||
|
|
||||||
|
temp = a;
|
||||||
|
|
||||||
|
assert(temp.length == 2);
|
||||||
|
assert(temp[0].length == 3);
|
||||||
|
assert(temp[1].length == 4);
|
||||||
|
assert(temp[1][0].value == 4);
|
||||||
|
assert(temp[1][1].value == 5);
|
||||||
|
assert(temp[1][2].value == 6);
|
||||||
|
assert(temp[1][3].value == 7);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test3() external returns (bool) {
|
||||||
|
S[][] memory temp = new S[][](2);
|
||||||
|
|
||||||
|
temp[0] = a[0];
|
||||||
|
temp[1] = a[1];
|
||||||
|
|
||||||
|
assert(temp.length == 2);
|
||||||
|
assert(temp[0].length == 3);
|
||||||
|
assert(temp[1].length == 4);
|
||||||
|
assert(temp[1][0].value == 4);
|
||||||
|
assert(temp[1][1].value == 5);
|
||||||
|
assert(temp[1][2].value == 6);
|
||||||
|
assert(temp[1][3].value == 7);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test4() external returns (bool) {
|
||||||
|
S[][] memory temp = new S[][](2);
|
||||||
|
|
||||||
|
temp[0] = a[0];
|
||||||
|
temp[1] = b;
|
||||||
|
|
||||||
|
assert(temp.length == 2);
|
||||||
|
assert(temp[0].length == 3);
|
||||||
|
assert(temp[1].length == 4);
|
||||||
|
assert(temp[1][0].value == 4);
|
||||||
|
assert(temp[1][1].value == 5);
|
||||||
|
assert(temp[1][2].value == 6);
|
||||||
|
assert(temp[1][3].value == 7);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >homestead
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// test1() -> true
|
||||||
|
// gas irOptimized: 150618
|
||||||
|
// gas legacy: 150266
|
||||||
|
// gas legacyOptimized: 149875
|
||||||
|
// test2() -> true
|
||||||
|
// test3() -> true
|
||||||
|
// test4() -> true
|
@ -0,0 +1,44 @@
|
|||||||
|
pragma abicoder v2;
|
||||||
|
struct S {
|
||||||
|
function () external[] functions;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract C {
|
||||||
|
function f(function () external[] calldata functions) external returns (S memory) {
|
||||||
|
S memory s;
|
||||||
|
s.functions = functions;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract Test {
|
||||||
|
C immutable c = new C();
|
||||||
|
|
||||||
|
function test() external returns (bool) {
|
||||||
|
function() external[] memory functions = new function() external[](3);
|
||||||
|
|
||||||
|
functions[0] = this.random1;
|
||||||
|
functions[1] = this.random2;
|
||||||
|
functions[2] = this.random3;
|
||||||
|
|
||||||
|
S memory ret = c.f(functions);
|
||||||
|
|
||||||
|
assert(ret.functions.length == 3);
|
||||||
|
assert(ret.functions[0] == this.random1);
|
||||||
|
assert(ret.functions[1] == this.random2);
|
||||||
|
assert(ret.functions[2] == this.random3);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
function random1() external {
|
||||||
|
}
|
||||||
|
function random2() external {
|
||||||
|
}
|
||||||
|
function random3() external {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >homestead
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// test() -> true
|
@ -0,0 +1,45 @@
|
|||||||
|
pragma abicoder v2;
|
||||||
|
|
||||||
|
struct St0 {
|
||||||
|
bytes el0;
|
||||||
|
}
|
||||||
|
contract C {
|
||||||
|
function f() external returns (St0 memory) {
|
||||||
|
St0 memory x;
|
||||||
|
x.el0 = msg.data;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
function g() external returns (St0 memory) {
|
||||||
|
bytes memory temp = msg.data;
|
||||||
|
St0 memory x;
|
||||||
|
x.el0 = temp;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hashes() external returns (bytes4, bytes4) {
|
||||||
|
return (this.f.selector, this.g.selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
function large(uint256, uint256, uint256, uint256) external returns (St0 memory) {
|
||||||
|
St0 memory x;
|
||||||
|
x.el0 = msg.data;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
function another_large(uint256, uint256, uint256, uint256) external returns (St0 memory) {
|
||||||
|
bytes memory temp = msg.data;
|
||||||
|
St0 memory x;
|
||||||
|
x.el0 = temp;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f() -> 0x20, 0x20, 4, 0x26121ff000000000000000000000000000000000000000000000000000000000
|
||||||
|
// g() -> 0x20, 0x20, 4, 0xe2179b8e00000000000000000000000000000000000000000000000000000000
|
||||||
|
// hashes() -> 0x26121ff000000000000000000000000000000000000000000000000000000000, 0xe2179b8e00000000000000000000000000000000000000000000000000000000
|
||||||
|
// large(uint256,uint256,uint256,uint256): 1, 2, 3, 4 -> 0x20, 0x20, 0x84, 0xe02492f800000000000000000000000000000000000000000000000000000000, 0x100000000000000000000000000000000000000000000000000000000, 0x200000000000000000000000000000000000000000000000000000000, 0x300000000000000000000000000000000000000000000000000000000, 0x400000000000000000000000000000000000000000000000000000000
|
||||||
|
// another_large(uint256,uint256,uint256,uint256): 1, 2, 3, 4 -> 0x20, 0x20, 0x84, 0x2a46f85a00000000000000000000000000000000000000000000000000000000, 0x100000000000000000000000000000000000000000000000000000000, 0x200000000000000000000000000000000000000000000000000000000, 0x300000000000000000000000000000000000000000000000000000000, 0x400000000000000000000000000000000000000000000000000000000
|
@ -0,0 +1,9 @@
|
|||||||
|
// Example from https://github.com/ethereum/solidity/issues/12558
|
||||||
|
pragma abicoder v2;
|
||||||
|
contract C {
|
||||||
|
function() external[1][] s0;
|
||||||
|
constructor(function() external[1][] memory i0)
|
||||||
|
{
|
||||||
|
i0[0] = s0[1];
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user