mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Respect memory model for revert.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user