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(), ""); solAssert(_type.isValueType(), "");
if (auto const* funType = dynamic_cast<FunctionType const*>(&_type)) Whiskers templ(R"(
if (funType->kind() == FunctionType::Kind::External) function <functionName>(ptr) -> <returnVariables> {
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 {
<?fromCalldata> <?fromCalldata>
value := calldataload(ptr) let value := calldataload(ptr)
<validate>(value) <validate>(value)
<!fromCalldata> <!fromCalldata>
value := <cleanup>(mload(ptr)) let value := <cleanup>(mload(ptr))
</fromCalldata> </fromCalldata>
<returnVariables> :=
<?externalFunction>
<splitFunction>(value)
<!externalFunction>
value
</externalFunction>
} }
)") )");
("functionName", functionName) templ("functionName", functionName);
("fromCalldata", _fromCalldata) templ("fromCalldata", _fromCalldata);
("validate", validatorFunction(_type, true)) 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. // Byte array elements generally need cleanup.
// Other types are cleaned as well to account for dirty memory e.g. due to inline assembly. // Other types are cleaned as well to account for dirty memory e.g. due to inline assembly.
("cleanup", cleanupFunction(_type)) templ("cleanup", cleanupFunction(_type));
.render(); return templ.render();
}); });
} }

View File

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