Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions libsolidity/codegen/YulUtilFunctions.cpp
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you check #16066 (comment)? We should really check why something like true ? (a, true) : (a, true) does not trigger this bug. This may mean that either we're not doing an array conversion in some case were we need it or that we shouldn't be doing it in the true ? (a, 0) : (a, 0) case.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR is missing a changelog entry.

Original file line number Diff line number Diff line change
Expand Up @@ -3858,11 +3858,18 @@ std::string YulUtilFunctions::copyStructToStorageFunction(StructType const& _fro

std::string YulUtilFunctions::arrayConversionFunction(ArrayType const& _from, ArrayType const& _to)
{
if (_to.dataStoredIn(DataLocation::CallData))
solAssert(
_from.dataStoredIn(DataLocation::CallData) && _from.isByteArrayOrString() && _to.isByteArrayOrString(),
""
);
solAssert(
!_to.dataStoredIn(DataLocation::CallData) ||
Comment on lines -3861 to +3862
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd keep the if here. This is usually more readable than the negation you have to add to incorporate it into condition and our asserts are not debug anyway (we don't remove them from release builds).

(
_from.dataStoredIn(DataLocation::CallData) &&
(
(_from.isByteArrayOrString() && _to.isByteArrayOrString()) ||
(_from.baseType() == _to.baseType())
)
),
"Conversion to calldata array is possible only from calldata array of the same type or for "
"(bytes calldata) <-> (string calldata) conversion."
);

// Other cases are done explicitly in LValue::storeValue, and only possible by assignment.
if (_to.location() == DataLocation::Storage)
Expand Down
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add tests for slices and static arrays as well. At least the latter also trigger the ICE.

contract C {
    function f(uint[] calldata a) public {
        (uint[] calldata b, ) = true ? (a[:], 0) : (a[0:1], 0);
    }
}
contract C {
    function f(uint[3] calldata a) public {
        (uint[3] calldata b, ) = true ? (a, 0) : (a, 0);
    }
}

Also a mix of arrays and slices ((a, 0) : (a[:], 0)).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH I'd have no idea what this test does just from the current name. What do you mean by "ordinary types"?

This should be way more specific:
conversion_of_ordinary_types_array.sol -> non_byte_calldata_array_conversion_in_ternary_with_tuple_operands.sol

Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
pragma abicoder v2;

contract C {
function g(uint[] calldata a) public returns(uint, uint, uint, uint) {
(uint[] calldata b, ) = true ? (a, 0) : (a, 0);
return (b.length, b[0], b[1], b[2]);
}
Comment on lines +4 to +7
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd put this bit in a separate file. It's independent of the larger case, and when one of those fails it's usually nicer to have a smaller one that's easier to understand to debug.


struct N {
address addr;
bytes data;
}

struct S {
uint8 a;
address addr;
N[] ns;
bytes data;
}

function g() public returns(S[] memory) {
S[] memory ss = new S[](3);
ss[0].addr = address(this);
ss[0].a = 123;
ss[0].ns = new N[](1);

ss[0].ns[0].addr = address(this);
ss[0].ns[0].data = "abdeff00";

ss[0].data = "abdeff";
Comment on lines +25 to +30
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ss[0].ns = new N[](1);
ss[0].ns[0].addr = address(this);
ss[0].ns[0].data = "abdeff00";
ss[0].data = "abdeff";
ss[0].ns = new N[](1);
ss[0].ns[0].addr = address(this);
ss[0].ns[0].data = "abdeff00";
ss[0].data = "abdeff";


ss[1].addr = msg.sender;
ss[1].a = 124;
ss[1].ns = new N[](2);
ss[1].ns[0].addr = msg.sender;
ss[1].ns[0].data = "abdeff10";
ss[1].ns[1].addr = msg.sender;
ss[1].ns[1].data = "abdeff11";
ss[1].data = "deabff";

ss[2].addr = tx.origin;
ss[2].a = 125;
ss[2].ns = new N[](3);
ss[2].ns[0].addr = tx.origin;
ss[2].ns[0].data = "abdeff20";
ss[2].ns[1].addr = tx.origin;
ss[2].ns[1].data = "abdeff21";
ss[2].ns[2].addr = tx.origin;
ss[2].ns[2].data = "abdeff22";
ss[2].data = "deffab";

return ss;
}

function g(S[] calldata a) public returns(S[] memory) {
(S[] calldata b, ) = true ? (a, 0) : (a, 0);
return b;
}
}
// Two last results and input to last call must all be equal.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better if the expectations were just formatted in a way that makes it more obvious at a glance that they're correct.

For example you could format strings as actual strings (soltest does accept those). I'd also use some regular-looking hard-coded addresses instead of things like tx.origin and msg.sender or address(this). Those are pretty noisy-looking, not easy to fish out visually. For fields with lots of zeros you can either use hex strings (those are not automatically padded to 32 bytes unlike integers) or left()/right() helpers to pad a shorter value to 32 bytes. I also usually use hex for offsets but decimals for sizes, which makes encoding a bit easier to decode visually.

Having to read it very carefully quickly gets tedious when reading a lot of tests. Overall we should try a bit harder optimize expectations for being able to quickly verifying them.

// ----
// g(uint256[]): 0x20, 3, 11111111, 2222222, 888888888 -> 3, 11111111, 2222222, 888888888
// g()
// ->
// 0x20, 0x03, 0x60, 0x01e0, 0x0400, 0x7b, 0xc06afe3a8444fc0004668591e8306bfb9968e79e, 0x80, 0x0140, 0x01, 0x20, 1098512253422041666021416798982440481960491542430, 0x40, 8, 0x6162646566663030000000000000000000000000000000000000000000000000, 6, 44048190233298227891509493227738300628996713231762343836654645076567135354880, 0x7c, 0x1212121212121212121212121212120000000012, 0x80, 0x01e0, 0x02, 0x40, 0xc0, 0x1212121212121212121212121212120000000012, 0x40, 0x08, 0x6162646566663130000000000000000000000000000000000000000000000000, 0x1212121212121212121212121212120000000012, 0x40, 0x08, 0x6162646566663131000000000000000000000000000000000000000000000000, 6, 45410408534123481836474933912542458712564453942015096274585020526880243056640, 0x7d, 0x9292929292929292929292929292929292929292, 0x80, 0x0280, 0x03, 0x60, 0xe0, 0x0160, 0x9292929292929292929292929292929292929292, 0x40, 0x08, 0x6162646566663230000000000000000000000000000000000000000000000000, 0x9292929292929292929292929292929292929292, 0x40, 0x08, 0x6162646566663231000000000000000000000000000000000000000000000000, 0x9292929292929292929292929292929292929292, 0x40, 0x08, 0x6162646566663232000000000000000000000000000000000000000000000000, 6, 45410443150166795494996323125458085338169329380009076603811707127780899553280
// g((uint8,address,(address,bytes)[],bytes)[]):
// 0x20, 0x03, 0x60, 0x01e0, 0x0400, 0x7b, 0xc06afe3a8444fc0004668591e8306bfb9968e79e, 0x80, 0x0140, 0x01, 0x20, 1098512253422041666021416798982440481960491542430, 0x40, 8, 0x6162646566663030000000000000000000000000000000000000000000000000, 6, 44048190233298227891509493227738300628996713231762343836654645076567135354880, 0x7c, 0x1212121212121212121212121212120000000012, 0x80, 0x01e0, 0x02, 0x40, 0xc0, 0x1212121212121212121212121212120000000012, 0x40, 0x08, 0x6162646566663130000000000000000000000000000000000000000000000000, 0x1212121212121212121212121212120000000012, 0x40, 0x08, 0x6162646566663131000000000000000000000000000000000000000000000000, 6, 45410408534123481836474933912542458712564453942015096274585020526880243056640, 0x7d, 0x9292929292929292929292929292929292929292, 0x80, 0x0280, 0x03, 0x60, 0xe0, 0x0160, 0x9292929292929292929292929292929292929292, 0x40, 0x08, 0x6162646566663230000000000000000000000000000000000000000000000000, 0x9292929292929292929292929292929292929292, 0x40, 0x08, 0x6162646566663231000000000000000000000000000000000000000000000000, 0x9292929292929292929292929292929292929292, 0x40, 0x08, 0x6162646566663232000000000000000000000000000000000000000000000000, 6, 45410443150166795494996323125458085338169329380009076603811707127780899553280
// ->
//0x20, 0x03, 0x60, 0x01e0, 0x0400, 0x7b, 0xc06afe3a8444fc0004668591e8306bfb9968e79e, 0x80, 0x0140, 0x01, 0x20, 1098512253422041666021416798982440481960491542430, 0x40, 8, 0x6162646566663030000000000000000000000000000000000000000000000000, 6, 44048190233298227891509493227738300628996713231762343836654645076567135354880, 0x7c, 0x1212121212121212121212121212120000000012, 0x80, 0x01e0, 0x02, 0x40, 0xc0, 0x1212121212121212121212121212120000000012, 0x40, 0x08, 0x6162646566663130000000000000000000000000000000000000000000000000, 0x1212121212121212121212121212120000000012, 0x40, 0x08, 0x6162646566663131000000000000000000000000000000000000000000000000, 6, 45410408534123481836474933912542458712564453942015096274585020526880243056640, 0x7d, 0x9292929292929292929292929292929292929292, 0x80, 0x0280, 0x03, 0x60, 0xe0, 0x0160, 0x9292929292929292929292929292929292929292, 0x40, 0x08, 0x6162646566663230000000000000000000000000000000000000000000000000, 0x9292929292929292929292929292929292929292, 0x40, 0x08, 0x6162646566663231000000000000000000000000000000000000000000000000, 0x9292929292929292929292929292929292929292, 0x40, 0x08, 0x6162646566663232000000000000000000000000000000000000000000000000, 6, 45410443150166795494996323125458085338169329380009076603811707127780899553280