Skip to content

Commit

Permalink
Perform bounds checking before reading array length.
Browse files Browse the repository at this point in the history
  • Loading branch information
chriseth committed Nov 16, 2017
1 parent f75a45a commit cc3b651
Showing 1 changed file with 7 additions and 7 deletions.
14 changes: 7 additions & 7 deletions libsolidity/codegen/ABIFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1059,6 +1059,10 @@ string ABIFunctions::abiEncodingFunctionFunctionType(

string ABIFunctions::abiDecodingFunction(Type const& _type, bool _fromMemory, bool _forUseOnStack)
{
// The decoding function has to perform bounds checks unless it decodes a value type.
// Conversely, bounds checks have to be performed before the decoding function
// of a value type is called.

TypePointer decodingType = _type.decodingType();
solAssert(decodingType, "");

Expand Down Expand Up @@ -1130,6 +1134,7 @@ string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool _from
R"(
// <readableTypeName>
function <functionName>(offset, end) -> array {
switch slt(add(offset, 0x1f), end) case 0 { revert(0, 0) }
let length := <retrieveLength>
array := <allocate>(<allocationSize>(length))
let dst := array
Expand All @@ -1139,7 +1144,6 @@ string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool _from
for { let i := 0 } lt(i, length) { i := add(i, 1) }
{
let elementPos := <retrieveElementPos>
<dynamicBoundsCheck>
mstore(dst, <decodingFun>(elementPos, end))
dst := add(dst, 0x20)
src := add(src, <baseEncodedSize>)
Expand All @@ -1160,18 +1164,12 @@ string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool _from
{
templ("staticBoundsCheck", "");
templ("retrieveElementPos", "add(offset, " + load + "(src))");
// The dynamic bounds check might not be needed (because we have an additional check
// one level deeper), but we keep it in just in case. This at least prevents
// the part one level deeper from reading the length from an out of bounds position.
// Also it performs overflow checks for the data pointer.
templ("dynamicBoundsCheck", "switch or(slt(elementPos, offset), gt(elementPos, end)) case 1 { revert(0, 0) }");
templ("baseEncodedSize", "0x20");
}
else
{
string baseEncodedSize = toCompactHexWithPrefix(_type.baseType()->calldataEncodedSize());
templ("staticBoundsCheck", "switch gt(add(src, mul(length, " + baseEncodedSize + ")), end) case 1 { revert(0, 0) }");
templ("dynamicBoundsCheck", "");
templ("retrieveElementPos", "src");
templ("baseEncodedSize", baseEncodedSize);
}
Expand Down Expand Up @@ -1199,6 +1197,7 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type)
templ = R"(
// <readableTypeName>
function <functionName>(offset, end) -> arrayPos, length {
switch slt(add(offset, 0x1f), end) case 0 { revert(0, 0) }
length := calldataload(offset)
switch gt(length, 0xffffffffffffffff) case 1 { revert(0, 0) }
arrayPos := add(offset, 0x20)
Expand Down Expand Up @@ -1236,6 +1235,7 @@ string ABIFunctions::abiDecodingFunctionByteArray(ArrayType const& _type, bool _
Whiskers templ(
R"(
function <functionName>(offset, end) -> array {
switch slt(add(offset, 0x1f), end) case 0 { revert(0, 0) }
let length := <load>(offset)
array := <allocate>(<allocationSize>(length))
mstore(array, length)
Expand Down

0 comments on commit cc3b651

Please sign in to comment.