From 061fecbc90c855c6f3055775fa23a33959dd4b81 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Mon, 28 Dec 2020 19:40:17 -0500 Subject: [PATCH] [whiskers] Add check that template contain tags. --- libsolidity/codegen/ABIFunctions.cpp | 25 +++++++++++++----------- libsolidity/codegen/YulUtilFunctions.cpp | 8 -------- libsolidity/codegen/ir/IRGenerator.cpp | 1 - libsolutil/Whiskers.cpp | 16 +++++++++++++++ libsolutil/Whiskers.h | 8 +++++++- test/libsolutil/Whiskers.cpp | 2 +- 6 files changed, 38 insertions(+), 22 deletions(-) diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index b6a479e74..d2512881a 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -1231,9 +1231,10 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type) "abi_decode_" + _type.identifier(); return createFunction(functionName, [&]() { - string templ; + Whiskers w; if (_type.isDynamicallySized()) - templ = R"( + { + w = Whiskers(R"( // function (offset, end) -> arrayPos, length { if iszero(slt(add(offset, 0x1f), end)) { } @@ -1242,25 +1243,27 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type) arrayPos := add(offset, 0x20) if gt(add(arrayPos, mul(length, )), end) { } } - )"; + )"); + w("revertStringOffset", revertReasonIfDebug("ABI decoding: invalid calldata array offset")); + w("revertStringLength", revertReasonIfDebug("ABI decoding: invalid calldata array length")); + } else - templ = R"( + { + w = Whiskers(R"( // function (offset, end) -> arrayPos { arrayPos := offset if gt(add(arrayPos, mul(, )), end) { } } - )"; - Whiskers w{templ}; - // TODO add test - w("revertStringOffset", revertReasonIfDebug("ABI decoding: invalid calldata array offset")); - w("revertStringLength", revertReasonIfDebug("ABI decoding: invalid calldata array length")); + )"); + w("length", toCompactHexWithPrefix(_type.length())); + } w("revertStringPos", revertReasonIfDebug("ABI decoding: invalid calldata array stride")); w("functionName", functionName); w("readableTypeName", _type.toString(true)); w("stride", toCompactHexWithPrefix(_type.calldataStride())); - if (!_type.isDynamicallySized()) - w("length", toCompactHexWithPrefix(_type.length())); + + // TODO add test return w.render(); }); } diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 2fd5640f1..b66b9cf25 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -959,7 +959,6 @@ string YulUtilFunctions::overflowCheckedUnsignedExpFunction() ("functionName", functionName) ("panic", panicFunction(PanicCode::UnderOverflow)) ("expLoop", overflowCheckedExpLoopFunction()) - ("shr_1", shiftRightFunction(1)) .render(); }); } @@ -1326,8 +1325,6 @@ string YulUtilFunctions::byteArrayTransitLongToShortFunction(ArrayType const& _t ("functionName", functionName) ("dataPosition", arrayDataAreaFunction(_type)) ("extractUsedApplyLen", shortByteArrayEncodeUsedAreaSetLengthFunction()) - ("shl", shiftLeftFunctionDynamic()) - ("ones", formatNumber((bigint(1) << 256) - 1)) .render(); }); } @@ -1420,7 +1417,6 @@ string YulUtilFunctions::storageByteArrayPopFunction(ArrayType const& _type) ("encodeUsedSetLen", shortByteArrayEncodeUsedAreaSetLengthFunction()) ("indexAccess", storageArrayIndexAccessFunction(_type)) ("setToZero", storageSetToZeroFunction(*_type.baseType())) - ("shl", shiftLeftFunctionDynamic()) .render(); }); } @@ -1492,7 +1488,6 @@ string YulUtilFunctions::storageArrayPushFunction(ArrayType const& _type, Type c ("storeValue", updateStorageValueFunction(*_fromType, *_type.baseType())) ("maxArrayLength", (u256(1) << 64).str()) ("shl", shiftLeftFunctionDynamic()) - ("shr", shiftRightFunction(248)) .render(); }); } @@ -1658,7 +1653,6 @@ string YulUtilFunctions::clearStorageStructFunction(StructType const& _type) } )") ("functionName", functionName) - ("storageSize", _type.storageSize().str()) ("member", memberSetValues) .render(); }); @@ -1742,7 +1736,6 @@ string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromType, templ("srcDataLocation", arrayDataAreaFunction(_fromType)); if (fromCalldata) { - templ("dynamicallySizedBase", _fromType.baseType()->isDynamicallySized()); templ("dynamicallyEncodedBase", _fromType.baseType()->isDynamicallyEncoded()); if (_fromType.baseType()->isDynamicallyEncoded()) templ("accessCalldataTail", accessCalldataTailFunction(*_fromType.baseType())); @@ -3380,7 +3373,6 @@ string YulUtilFunctions::copyStructToStorageFunction(StructType const& _from, St solAssert(srcOffset == 0, ""); } - t("memberStorageSlotOffset", to_string(offset)); t("updateStorageValue", updateStorageValueFunction( memberType, *toStructMembers[i].type, diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index 22b506291..c91e2536e 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -891,7 +891,6 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) } t("fallback", fallbackCode); - t("revertNoSignature", ""); } else t( diff --git a/libsolutil/Whiskers.cpp b/libsolutil/Whiskers.cpp index 3049af5c4..e236104c7 100644 --- a/libsolutil/Whiskers.cpp +++ b/libsolutil/Whiskers.cpp @@ -40,6 +40,7 @@ Whiskers& Whiskers::operator()(string _parameter, string _value) { checkParameterValid(_parameter); checkParameterUnknown(_parameter); + checkTemplateContainsTags(_parameter, {""}); m_parameters[move(_parameter)] = move(_value); return *this; } @@ -48,6 +49,7 @@ Whiskers& Whiskers::operator()(string _parameter, bool _value) { checkParameterValid(_parameter); checkParameterUnknown(_parameter); + checkTemplateContainsTags(_parameter, {"?", "/"}); m_conditions[move(_parameter)] = _value; return *this; } @@ -59,6 +61,7 @@ Whiskers& Whiskers::operator()( { checkParameterValid(_listParameter); checkParameterUnknown(_listParameter); + checkTemplateContainsTags(_listParameter, {"#", "/"}); for (auto const& element: _values) for (auto const& val: element) checkParameterValid(val.first); @@ -100,6 +103,19 @@ void Whiskers::checkParameterUnknown(string const& _parameter) const ); } +void Whiskers::checkTemplateContainsTags(string const& _parameter, vector const& _prefixes) const +{ + for (auto const& prefix: _prefixes) + { + string tag{"<" + prefix + _parameter + ">"}; + assertThrow( + m_template.find(tag) != string::npos, + WhiskersError, + "Tag '" + tag + "' not found in template:\n" + m_template + ); + } +} + namespace { template diff --git a/libsolutil/Whiskers.h b/libsolutil/Whiskers.h index 5ddb7a884..113fbe6ed 100644 --- a/libsolutil/Whiskers.h +++ b/libsolutil/Whiskers.h @@ -73,7 +73,7 @@ public: using StringMap = std::map; using StringListMap = std::map>; - explicit Whiskers(std::string _template); + explicit Whiskers(std::string _template = ""); /// Sets a single regular parameter, . Whiskers& operator()(std::string _parameter, std::string _value); @@ -94,6 +94,12 @@ private: void checkParameterValid(std::string const& _parameter) const; void checkParameterUnknown(std::string const& _parameter) const; + /// Checks whether the string stored in `m_template` contains all the tags specified. + /// @param _parameter name of the parameter. This name is used to construct the tag(s). + /// @param _prefixes a vector of strings, where each element is used to compose the tag + /// like `"<" + element + _parameter + ">"`. Each element of _prefixes is used as a prefix of the tag name. + void checkTemplateContainsTags(std::string const& _parameter, std::vector const& _prefixes) const; + static std::string replace( std::string const& _template, StringMap const& _parameters, diff --git a/test/libsolutil/Whiskers.cpp b/test/libsolutil/Whiskers.cpp index 1cc889127..3ccaa64da 100644 --- a/test/libsolutil/Whiskers.cpp +++ b/test/libsolutil/Whiskers.cpp @@ -190,7 +190,7 @@ BOOST_AUTO_TEST_CASE(parameter_collision) vector> list(1); list[0]["a"] = "x"; Whiskers m(templ); - m("a", "X")("b", list); + BOOST_CHECK_THROW(m("a", "X")("b", list), WhiskersError); BOOST_CHECK_THROW(m.render(), WhiskersError); }