Update expectations for uninitialized internal function.

This commit is contained in:
chriseth 2021-01-18 19:02:57 +01:00
parent 87a68feea1
commit c3d3415207
4 changed files with 53 additions and 18 deletions

View File

@ -114,3 +114,22 @@ This causes differences in some contracts, for example:
Previously `f()` would return `0x6465616462656566313564656164000000000000000000000000000000000010` (it has correct length, and correct first 8 elements, but than it contains dirty data which was set via assembly).
Now it is returning `0x6465616462656566000000000000000000000000000000000000000000000010` (it has correct length, and correct elements, but doesn't contain dirty data).
Internals
=========
Internal function pointers:
The old code generator uses code offsets or tags for values of internal function pointers. This is especially complicated since
these offsets are different at construction time and after deployment and the values can cross this border via storage.
Because of that, both offsets are encoded at construction time into the same value (into different bytes).
In the new code generator, function pointers use the AST IDs of the functions as values. Since calls via jumps are not possible,
calls through function pointers always have to use an internal dispatch function that uses the ``switch`` statement to select
the right function.
The ID ``0`` is reserved for uninitialized function pointers which then cause a panic in the disptach function when called.
In the old code generator, internal function pointers are initialized with a special function that always causes a panic.
This causes a storage write at construction time for internal function pointers in storage.

View File

@ -5615,24 +5615,6 @@ BOOST_AUTO_TEST_CASE(event_wrong_abi_name)
)
}
BOOST_AUTO_TEST_CASE(uninitialized_internal_storage_function)
{
char const* sourceCode = R"(
contract Test {
function() internal x;
function f() public returns (uint r) {
function() internal t = x;
assembly { r := t }
}
}
)";
compileAndRun(sourceCode, 0, "Test");
bytes result = callContractFunction("f()");
BOOST_CHECK(!result.empty());
BOOST_CHECK(result != encodeArgs(0));
}
BOOST_AUTO_TEST_CASE(dirty_scratch_space_prior_to_constant_optimiser)
{
char const* sourceCode = R"(

View File

@ -0,0 +1,17 @@
contract Test {
function() internal x;
function f() public returns (bool) {
function() internal t = x;
// The legacy codegen would use a specific function
// entry tag that always panics.
// Via Yul, the internal dispatch will panic instead.
uint z;
assembly { z := t }
assert(z != 0);
return true;
}
}
// ====
// compileViaYul: false
// ----
// f() -> true

View File

@ -0,0 +1,17 @@
contract Test {
function() internal x;
function f() public returns (bool) {
function() internal t = x;
// The legacy codegen would use a specific function
// entry tag that always panics.
// Via Yul, the internal dispatch will panic instead.
uint z;
assembly { z := t }
assert(z == 0);
return true;
}
}
// ====
// compileViaYul: true
// ----
// f() -> true