Skip to content

Fix ICE when assigning calldata Struct with external function type member to storage variable. - #16764

Open
matheusaaguiar wants to merge 2 commits into
developfrom
fix-ice-copy-struct-function-type-member-copy-calldata-to-storage
Open

Fix ICE when assigning calldata Struct with external function type member to storage variable.#16764
matheusaaguiar wants to merge 2 commits into
developfrom
fix-ice-copy-struct-function-type-member-copy-calldata-to-storage

Conversation

@matheusaaguiar

Copy link
Copy Markdown
Contributor

fix #16717.

@matheusaaguiar
matheusaaguiar force-pushed the fix-ice-copy-struct-function-type-member-copy-calldata-to-storage branch from 03cb6af to 55d0c56 Compare May 22, 2026 22:20
@github-actions github-actions Bot added the stale The issue/PR was marked as stale because it has been open for too long. label Jun 6, 2026
@github-actions github-actions Bot closed this Jun 13, 2026
@matheusaaguiar matheusaaguiar self-assigned this Jun 18, 2026
@matheusaaguiar matheusaaguiar removed stale The issue/PR was marked as stale because it has been open for too long. closed-due-inactivity labels Jun 18, 2026
@argotorg argotorg deleted a comment from github-actions Bot Jun 18, 2026
@argotorg argotorg deleted a comment from github-actions Bot Jun 18, 2026
@matheusaaguiar
matheusaaguiar force-pushed the fix-ice-copy-struct-function-type-member-copy-calldata-to-storage branch from 55d0c56 to 0a3f7a4 Compare June 18, 2026 13:07
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

This pull request is stale because it has been open for 14 days with no activity.
It will be closed in 7 days unless the stale label is removed.

@github-actions github-actions Bot added the stale The issue/PR was marked as stale because it has been open for too long. label Jul 3, 2026
@cameel cameel removed the stale The issue/PR was marked as stale because it has been open for too long. label Jul 5, 2026
Comment thread libsolidity/codegen/YulUtilFunctions.cpp
Comment thread Changelog.md Outdated
* General: Remove support for the experimental EOF (EVM Object Format) backend.

Bugfixes:
* Codegen: Fix ICE when assigning a calldata struct containing a member of external function type to a storage struct.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Gonna have to move this up into 0.8.37.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would add a few more tests:

  1. struct with external function ptr + uint64 (packing)
  2. struct with external function ptr + uint256[] array (dynamic)
  3. array of structs with external function ptr, i.e.
contract C {
  S[] storageStruct;
  ....
}

@matheusaaguiar
matheusaaguiar force-pushed the fix-ice-copy-struct-function-type-member-copy-calldata-to-storage branch 3 times, most recently from 62d0bde to b6deae8 Compare July 17, 2026 20:52
@matheusaaguiar
matheusaaguiar force-pushed the fix-ice-copy-struct-function-type-member-copy-calldata-to-storage branch from b6deae8 to 7fba57e Compare August 3, 2026 22:34

@nikola-matic nikola-matic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I've got another test with malformed function pointers:

struct S {
    function(uint) external fn_uint;
}

contract C {
    S storageStruct;

    function test(S calldata calldataStruct) public returns (bool) {
        storageStruct = calldataStruct;
        return true;
    }
}
// ----
// test((function)): "01234567890123456789abcd" -> true
// test((function)): 0x3031323334353637383930313233343536373839616263640000000000000001 -> FAILURE
// test((function)): 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -> FAILURE

You can call this one copy_from_calldata_to_storage_external_function_type_member_invalid.sol.

Tests that 8 bytes of padding following the 24 byte address is zero, otherwise should revert (which it does, I ran it locally :)

Push this and I'll approve and merge.

@matheusaaguiar
matheusaaguiar force-pushed the fix-ice-copy-struct-function-type-member-copy-calldata-to-storage branch from 7fba57e to 1f287aa Compare August 4, 2026 15:09
@matheusaaguiar

Copy link
Copy Markdown
Contributor Author

@nikola-matic added your suggested test.

Comment on lines +3802 to +3810
<?dynamicallyEncodedMember>
let <memberValues> := <accessCalldataTail>(value, memberSrcPtr)
<!dynamicallyEncodedMember>
<?isValueType>
let <memberValues> := <read>(memberSrcPtr)
<!isValueType>
let <memberValues> := memberSrcPtr
</isValueType>
</dynamicallyEncodedMember>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This introduces a silent assumption that value types are never dynamically encoded. I think that's true now, but such types are technically possible in the encoding - it would be a case where you have an offset in the head and the value is fixed-size, but still stored in the tail.

No need to handle that, but please at least explicitly assert that dynamicallyEncodedMember && isValueType is impossible.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Right.
Though before, in that case, it would default to the one read method for value types, possibly generating a miscompilation, I guess.
Added an assertion in the form: p -> q (= !p v q), with p: dynamically encoded, q: not value type.

@matheusaaguiar
matheusaaguiar force-pushed the fix-ice-copy-struct-function-type-member-copy-calldata-to-storage branch from 1f287aa to 1c0f0e1 Compare August 4, 2026 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ICE: Invalid IR generated when assigning calldata struct with external function type member to storage

3 participants