Respect memory model for revert.

This commit is contained in:
chriseth
2021-05-03 18:23:41 +02:00
parent fe4822a1d2
commit 62355aead3
10 changed files with 114 additions and 104 deletions
+35 -35
View File
@@ -205,12 +205,12 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
Whiskers templ(R"(
function <functionName>(headStart, dataEnd) <arrow> <valueReturnParams> {
if slt(sub(dataEnd, headStart), <minimumSize>) { <revertString> }
if slt(sub(dataEnd, headStart), <minimumSize>) { <revertString>() }
<decodeElements>
}
)");
templ("functionName", functionName);
templ("revertString", revertReasonIfDebug("ABI decoding: tuple data too short"));
templ("revertString", revertReasonIfDebugFunction("ABI decoding: tuple data too short"));
templ("minimumSize", to_string(headSize(decodingTypes)));
string decodeElements;
@@ -235,7 +235,7 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
{
<?dynamic>
let offset := <load>(add(headStart, <pos>))
if gt(offset, 0xffffffffffffffff) { <revertString> }
if gt(offset, 0xffffffffffffffff) { <revertString>() }
<!dynamic>
let offset := <pos>
</dynamic>
@@ -244,7 +244,7 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
)");
elementTempl("dynamic", decodingTypes[i]->isDynamicallyEncoded());
// TODO add test
elementTempl("revertString", revertReasonIfDebug("ABI decoding: invalid tuple offset"));
elementTempl("revertString", revertReasonIfDebugFunction("ABI decoding: invalid tuple offset"));
elementTempl("load", _fromMemory ? "mload" : "calldataload");
elementTempl("values", boost::algorithm::join(valueNamesLocal, ", "));
elementTempl("pos", to_string(headPos));
@@ -487,12 +487,12 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
else
templ("scaleLengthByStride",
Whiskers(R"(
if gt(length, <maxLength>) { <revertString> }
if gt(length, <maxLength>) { <revertString>() }
length := mul(length, <stride>)
)")
("stride", toCompactHexWithPrefix(fromArrayType.calldataStride()))
("maxLength", toCompactHexWithPrefix(u256(-1) / fromArrayType.calldataStride()))
("revertString", revertReasonIfDebug("ABI encoding: array data too long"))
("revertString", revertReasonIfDebugFunction("ABI encoding: array data too long"))
.render()
// TODO add revert test
);
@@ -1148,14 +1148,14 @@ string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool _from
R"(
// <readableTypeName>
function <functionName>(offset, end) -> array {
if iszero(slt(add(offset, 0x1f), end)) { <revertString> }
if iszero(slt(add(offset, 0x1f), end)) { <revertString>() }
let length := <retrieveLength>
array := <abiDecodeAvailableLen>(<offset>, length, end)
}
)"
);
// TODO add test
templ("revertString", revertReasonIfDebug("ABI decoding: invalid calldata array offset"));
templ("revertString", revertReasonIfDebugFunction("ABI decoding: invalid calldata array offset"));
templ("functionName", functionName);
templ("readableTypeName", _type.toString(true));
templ("retrieveLength", _type.isDynamicallySized() ? (load + "(offset)") : toCompactHexWithPrefix(_type.length()));
@@ -1188,13 +1188,13 @@ string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType const& _t
</dynamic>
let src := offset
if gt(add(src, mul(length, <stride>)), end) {
<revertInvalidStride>
<revertInvalidStride>()
}
for { let i := 0 } lt(i, length) { i := add(i, 1) }
{
<?dynamicBase>
let innerOffset := <load>(src)
if gt(innerOffset, 0xffffffffffffffff) { <revertStringOffset> }
if gt(innerOffset, 0xffffffffffffffff) { <revertStringOffset>() }
let elementPos := add(offset, innerOffset)
<!dynamicBase>
let elementPos := src
@@ -1215,9 +1215,9 @@ string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType const& _t
templ("dynamicBase", _type.baseType()->isDynamicallyEncoded());
templ(
"revertInvalidStride",
revertReasonIfDebug("ABI decoding: invalid calldata array stride")
revertReasonIfDebugFunction("ABI decoding: invalid calldata array stride")
);
templ("revertStringOffset", revertReasonIfDebug("ABI decoding: invalid calldata array offset"));
templ("revertStringOffset", revertReasonIfDebugFunction("ABI decoding: invalid calldata array offset"));
templ("decodingFun", abiDecodingFunction(*_type.baseType(), _fromMemory, false));
return templ.render();
});
@@ -1241,15 +1241,15 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type)
w = Whiskers(R"(
// <readableTypeName>
function <functionName>(offset, end) -> arrayPos, length {
if iszero(slt(add(offset, 0x1f), end)) { <revertStringOffset> }
if iszero(slt(add(offset, 0x1f), end)) { <revertStringOffset>() }
length := calldataload(offset)
if gt(length, 0xffffffffffffffff) { <revertStringLength> }
if gt(length, 0xffffffffffffffff) { <revertStringLength>() }
arrayPos := add(offset, 0x20)
if gt(add(arrayPos, mul(length, <stride>)), end) { <revertStringPos> }
if gt(add(arrayPos, mul(length, <stride>)), end) { <revertStringPos>() }
}
)");
w("revertStringOffset", revertReasonIfDebug("ABI decoding: invalid calldata array offset"));
w("revertStringLength", revertReasonIfDebug("ABI decoding: invalid calldata array length"));
w("revertStringOffset", revertReasonIfDebugFunction("ABI decoding: invalid calldata array offset"));
w("revertStringLength", revertReasonIfDebugFunction("ABI decoding: invalid calldata array length"));
}
else
{
@@ -1257,12 +1257,12 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type)
// <readableTypeName>
function <functionName>(offset, end) -> arrayPos {
arrayPos := offset
if gt(add(arrayPos, mul(<length>, <stride>)), end) { <revertStringPos> }
if gt(add(arrayPos, mul(<length>, <stride>)), end) { <revertStringPos>() }
}
)");
w("length", toCompactHexWithPrefix(_type.length()));
}
w("revertStringPos", revertReasonIfDebug("ABI decoding: invalid calldata array stride"));
w("revertStringPos", revertReasonIfDebugFunction("ABI decoding: invalid calldata array stride"));
w("functionName", functionName);
w("readableTypeName", _type.toString(true));
w("stride", toCompactHexWithPrefix(_type.calldataStride()));
@@ -1288,11 +1288,11 @@ string ABIFunctions::abiDecodingFunctionByteArrayAvailableLength(ArrayType const
array := <allocate>(<allocationSize>(length))
mstore(array, length)
let dst := add(array, 0x20)
if gt(add(src, length), end) { <revertStringLength> }
if gt(add(src, length), end) { <revertStringLength>() }
<copyToMemFun>(src, dst, length)
}
)");
templ("revertStringLength", revertReasonIfDebug("ABI decoding: invalid byte array length"));
templ("revertStringLength", revertReasonIfDebugFunction("ABI decoding: invalid byte array length"));
templ("functionName", functionName);
templ("allocate", m_utils.allocationFunction());
templ("allocationSize", m_utils.arrayAllocationSizeFunction(_type));
@@ -1312,12 +1312,12 @@ string ABIFunctions::abiDecodingFunctionCalldataStruct(StructType const& _type)
Whiskers w{R"(
// <readableTypeName>
function <functionName>(offset, end) -> value {
if slt(sub(end, offset), <minimumSize>) { <revertString> }
if slt(sub(end, offset), <minimumSize>) { <revertString>() }
value := offset
}
)"};
// TODO add test
w("revertString", revertReasonIfDebug("ABI decoding: struct calldata too short"));
w("revertString", revertReasonIfDebugFunction("ABI decoding: struct calldata too short"));
w("functionName", functionName);
w("readableTypeName", _type.toString(true));
w("minimumSize", to_string(_type.isDynamicallyEncoded() ? _type.calldataEncodedTailSize() : _type.calldataEncodedSize(true)));
@@ -1337,7 +1337,7 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr
Whiskers templ(R"(
// <readableTypeName>
function <functionName>(headStart, end) -> value {
if slt(sub(end, headStart), <minimumSize>) { <revertString> }
if slt(sub(end, headStart), <minimumSize>) { <revertString>() }
value := <allocate>(<memorySize>)
<#members>
{
@@ -1348,7 +1348,7 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr
}
)");
// TODO add test
templ("revertString", revertReasonIfDebug("ABI decoding: struct data too short"));
templ("revertString", revertReasonIfDebugFunction("ABI decoding: struct data too short"));
templ("functionName", functionName);
templ("readableTypeName", _type.toString(true));
templ("allocate", m_utils.allocationFunction());
@@ -1365,7 +1365,7 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr
Whiskers memberTempl(R"(
<?dynamic>
let offset := <load>(add(headStart, <pos>))
if gt(offset, 0xffffffffffffffff) { <revertString> }
if gt(offset, 0xffffffffffffffff) { <revertString>() }
<!dynamic>
let offset := <pos>
</dynamic>
@@ -1373,7 +1373,7 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr
)");
memberTempl("dynamic", decodingType->isDynamicallyEncoded());
// TODO add test
memberTempl("revertString", revertReasonIfDebug("ABI decoding: invalid struct offset"));
memberTempl("revertString", revertReasonIfDebugFunction("ABI decoding: invalid struct offset"));
memberTempl("load", _fromMemory ? "mload" : "calldataload");
memberTempl("pos", to_string(headPos));
memberTempl("memoryOffset", toCompactHexWithPrefix(_type.memoryOffsetOfMember(member.name)));
@@ -1441,7 +1441,7 @@ string ABIFunctions::calldataAccessFunction(Type const& _type)
Whiskers w(R"(
function <functionName>(base_ref, ptr) -> <return> {
let rel_offset_of_tail := calldataload(ptr)
if iszero(slt(rel_offset_of_tail, sub(sub(calldatasize(), base_ref), sub(<neededLength>, 1)))) { <revertStringOffset> }
if iszero(slt(rel_offset_of_tail, sub(sub(calldatasize(), base_ref), sub(<neededLength>, 1)))) { <revertStringOffset>() }
value := add(rel_offset_of_tail, base_ref)
<handleLength>
}
@@ -1453,14 +1453,14 @@ string ABIFunctions::calldataAccessFunction(Type const& _type)
w("handleLength", Whiskers(R"(
length := calldataload(value)
value := add(value, 0x20)
if gt(length, 0xffffffffffffffff) { <revertStringLength> }
if sgt(base_ref, sub(calldatasize(), mul(length, <calldataStride>))) { <revertStringStride> }
if gt(length, 0xffffffffffffffff) { <revertStringLength>() }
if sgt(base_ref, sub(calldatasize(), mul(length, <calldataStride>))) { <revertStringStride>() }
)")
("calldataStride", toCompactHexWithPrefix(arrayType->calldataStride()))
// TODO add test
("revertStringLength", revertReasonIfDebug("Invalid calldata access length"))
("revertStringLength", revertReasonIfDebugFunction("Invalid calldata access length"))
// TODO add test
("revertStringStride", revertReasonIfDebug("Invalid calldata access stride"))
("revertStringStride", revertReasonIfDebugFunction("Invalid calldata access stride"))
.render());
w("return", "value, length");
}
@@ -1471,7 +1471,7 @@ string ABIFunctions::calldataAccessFunction(Type const& _type)
}
w("neededLength", toCompactHexWithPrefix(tailSize));
w("functionName", functionName);
w("revertStringOffset", revertReasonIfDebug("Invalid calldata access offset"));
w("revertStringOffset", revertReasonIfDebugFunction("Invalid calldata access offset"));
return w.render();
}
else if (_type.isValueType())
@@ -1555,7 +1555,7 @@ size_t ABIFunctions::numVariablesForType(Type const& _type, EncodingOptions cons
return _type.sizeOnStack();
}
std::string ABIFunctions::revertReasonIfDebug(std::string const& _message)
std::string ABIFunctions::revertReasonIfDebugFunction(std::string const& _message)
{
return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _message);
return m_utils.revertReasonIfDebugFunction(_message);
}