Merge pull request #10187 from ethereum/validateExternal

[SolYul] Properly validate external functions from calldata.
This commit is contained in:
chriseth 2020-11-03 14:29:28 +01:00 committed by GitHub
commit 06d0459a72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 24 deletions

View File

@ -3553,37 +3553,44 @@ string YulUtilFunctions::readFromMemoryOrCalldata(Type const& _type, bool _fromC
}
solAssert(_type.isValueType(), "");
if (auto const* funType = dynamic_cast<FunctionType const*>(&_type))
if (funType->kind() == FunctionType::Kind::External)
return Whiskers(R"(
function <functionName>(memPtr) -> addr, selector {
let combined := <load>(memPtr)
addr, selector := <splitFunction>(combined)
}
)")
("functionName", functionName)
("load", _fromCalldata ? "calldataload" : "mload")
("splitFunction", splitExternalFunctionIdFunction())
.render();
return Whiskers(R"(
function <functionName>(ptr) -> value {
Whiskers templ(R"(
function <functionName>(ptr) -> <returnVariables> {
<?fromCalldata>
value := calldataload(ptr)
let value := calldataload(ptr)
<validate>(value)
<!fromCalldata>
value := <cleanup>(mload(ptr))
let value := <cleanup>(mload(ptr))
</fromCalldata>
<returnVariables> :=
<?externalFunction>
<splitFunction>(value)
<!externalFunction>
value
</externalFunction>
}
)")
("functionName", functionName)
("fromCalldata", _fromCalldata)
("validate", validatorFunction(_type, true))
)");
templ("functionName", functionName);
templ("fromCalldata", _fromCalldata);
if (_fromCalldata)
templ("validate", validatorFunction(_type, true));
auto const* funType = dynamic_cast<FunctionType const*>(&_type);
if (funType && funType->kind() == FunctionType::Kind::External)
{
templ("externalFunction", true);
templ("splitFunction", splitExternalFunctionIdFunction());
templ("returnVariables", "addr, selector");
}
else
{
templ("externalFunction", false);
templ("returnVariables", "returnValue");
}
// Byte array elements generally need cleanup.
// Other types are cleaned as well to account for dirty memory e.g. due to inline assembly.
("cleanup", cleanupFunction(_type))
.render();
templ("cleanup", cleanupFunction(_type));
return templ.render();
});
}

View File

@ -16,6 +16,8 @@ contract C {
return (this.ggg(s.f), this.h(s));
}
}
// ====
// compileViaYul: also
// ----
// ffff(uint256): 0 -> 0, 0
// ggg(function): 0 -> 0