[whiskers] Add check that template contain tags.

This commit is contained in:
Alexander Arlt 2020-12-28 19:40:17 -05:00
parent a75b87c80e
commit 061fecbc90
6 changed files with 38 additions and 22 deletions

View File

@ -1231,9 +1231,10 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type)
"abi_decode_" + "abi_decode_" +
_type.identifier(); _type.identifier();
return createFunction(functionName, [&]() { return createFunction(functionName, [&]() {
string templ; Whiskers w;
if (_type.isDynamicallySized()) if (_type.isDynamicallySized())
templ = R"( {
w = Whiskers(R"(
// <readableTypeName> // <readableTypeName>
function <functionName>(offset, end) -> arrayPos, length { function <functionName>(offset, end) -> arrayPos, length {
if iszero(slt(add(offset, 0x1f), end)) { <revertStringOffset> } if iszero(slt(add(offset, 0x1f), end)) { <revertStringOffset> }
@ -1242,25 +1243,27 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type)
arrayPos := add(offset, 0x20) 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"));
}
else else
templ = R"( {
w = Whiskers(R"(
// <readableTypeName> // <readableTypeName>
function <functionName>(offset, end) -> arrayPos { function <functionName>(offset, end) -> arrayPos {
arrayPos := offset arrayPos := offset
if gt(add(arrayPos, mul(<length>, <stride>)), end) { <revertStringPos> } if gt(add(arrayPos, mul(<length>, <stride>)), end) { <revertStringPos> }
} }
)"; )");
Whiskers w{templ}; w("length", toCompactHexWithPrefix(_type.length()));
// TODO add test }
w("revertStringOffset", revertReasonIfDebug("ABI decoding: invalid calldata array offset"));
w("revertStringLength", revertReasonIfDebug("ABI decoding: invalid calldata array length"));
w("revertStringPos", revertReasonIfDebug("ABI decoding: invalid calldata array stride")); w("revertStringPos", revertReasonIfDebug("ABI decoding: invalid calldata array stride"));
w("functionName", functionName); w("functionName", functionName);
w("readableTypeName", _type.toString(true)); w("readableTypeName", _type.toString(true));
w("stride", toCompactHexWithPrefix(_type.calldataStride())); w("stride", toCompactHexWithPrefix(_type.calldataStride()));
if (!_type.isDynamicallySized())
w("length", toCompactHexWithPrefix(_type.length())); // TODO add test
return w.render(); return w.render();
}); });
} }

View File

@ -959,7 +959,6 @@ string YulUtilFunctions::overflowCheckedUnsignedExpFunction()
("functionName", functionName) ("functionName", functionName)
("panic", panicFunction(PanicCode::UnderOverflow)) ("panic", panicFunction(PanicCode::UnderOverflow))
("expLoop", overflowCheckedExpLoopFunction()) ("expLoop", overflowCheckedExpLoopFunction())
("shr_1", shiftRightFunction(1))
.render(); .render();
}); });
} }
@ -1326,8 +1325,6 @@ string YulUtilFunctions::byteArrayTransitLongToShortFunction(ArrayType const& _t
("functionName", functionName) ("functionName", functionName)
("dataPosition", arrayDataAreaFunction(_type)) ("dataPosition", arrayDataAreaFunction(_type))
("extractUsedApplyLen", shortByteArrayEncodeUsedAreaSetLengthFunction()) ("extractUsedApplyLen", shortByteArrayEncodeUsedAreaSetLengthFunction())
("shl", shiftLeftFunctionDynamic())
("ones", formatNumber((bigint(1) << 256) - 1))
.render(); .render();
}); });
} }
@ -1420,7 +1417,6 @@ string YulUtilFunctions::storageByteArrayPopFunction(ArrayType const& _type)
("encodeUsedSetLen", shortByteArrayEncodeUsedAreaSetLengthFunction()) ("encodeUsedSetLen", shortByteArrayEncodeUsedAreaSetLengthFunction())
("indexAccess", storageArrayIndexAccessFunction(_type)) ("indexAccess", storageArrayIndexAccessFunction(_type))
("setToZero", storageSetToZeroFunction(*_type.baseType())) ("setToZero", storageSetToZeroFunction(*_type.baseType()))
("shl", shiftLeftFunctionDynamic())
.render(); .render();
}); });
} }
@ -1492,7 +1488,6 @@ string YulUtilFunctions::storageArrayPushFunction(ArrayType const& _type, Type c
("storeValue", updateStorageValueFunction(*_fromType, *_type.baseType())) ("storeValue", updateStorageValueFunction(*_fromType, *_type.baseType()))
("maxArrayLength", (u256(1) << 64).str()) ("maxArrayLength", (u256(1) << 64).str())
("shl", shiftLeftFunctionDynamic()) ("shl", shiftLeftFunctionDynamic())
("shr", shiftRightFunction(248))
.render(); .render();
}); });
} }
@ -1658,7 +1653,6 @@ string YulUtilFunctions::clearStorageStructFunction(StructType const& _type)
} }
)") )")
("functionName", functionName) ("functionName", functionName)
("storageSize", _type.storageSize().str())
("member", memberSetValues) ("member", memberSetValues)
.render(); .render();
}); });
@ -1742,7 +1736,6 @@ string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromType,
templ("srcDataLocation", arrayDataAreaFunction(_fromType)); templ("srcDataLocation", arrayDataAreaFunction(_fromType));
if (fromCalldata) if (fromCalldata)
{ {
templ("dynamicallySizedBase", _fromType.baseType()->isDynamicallySized());
templ("dynamicallyEncodedBase", _fromType.baseType()->isDynamicallyEncoded()); templ("dynamicallyEncodedBase", _fromType.baseType()->isDynamicallyEncoded());
if (_fromType.baseType()->isDynamicallyEncoded()) if (_fromType.baseType()->isDynamicallyEncoded())
templ("accessCalldataTail", accessCalldataTailFunction(*_fromType.baseType())); templ("accessCalldataTail", accessCalldataTailFunction(*_fromType.baseType()));
@ -3380,7 +3373,6 @@ string YulUtilFunctions::copyStructToStorageFunction(StructType const& _from, St
solAssert(srcOffset == 0, ""); solAssert(srcOffset == 0, "");
} }
t("memberStorageSlotOffset", to_string(offset));
t("updateStorageValue", updateStorageValueFunction( t("updateStorageValue", updateStorageValueFunction(
memberType, memberType,
*toStructMembers[i].type, *toStructMembers[i].type,

View File

@ -891,7 +891,6 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
} }
t("fallback", fallbackCode); t("fallback", fallbackCode);
t("revertNoSignature", "");
} }
else else
t( t(

View File

@ -40,6 +40,7 @@ Whiskers& Whiskers::operator()(string _parameter, string _value)
{ {
checkParameterValid(_parameter); checkParameterValid(_parameter);
checkParameterUnknown(_parameter); checkParameterUnknown(_parameter);
checkTemplateContainsTags(_parameter, {""});
m_parameters[move(_parameter)] = move(_value); m_parameters[move(_parameter)] = move(_value);
return *this; return *this;
} }
@ -48,6 +49,7 @@ Whiskers& Whiskers::operator()(string _parameter, bool _value)
{ {
checkParameterValid(_parameter); checkParameterValid(_parameter);
checkParameterUnknown(_parameter); checkParameterUnknown(_parameter);
checkTemplateContainsTags(_parameter, {"?", "/"});
m_conditions[move(_parameter)] = _value; m_conditions[move(_parameter)] = _value;
return *this; return *this;
} }
@ -59,6 +61,7 @@ Whiskers& Whiskers::operator()(
{ {
checkParameterValid(_listParameter); checkParameterValid(_listParameter);
checkParameterUnknown(_listParameter); checkParameterUnknown(_listParameter);
checkTemplateContainsTags(_listParameter, {"#", "/"});
for (auto const& element: _values) for (auto const& element: _values)
for (auto const& val: element) for (auto const& val: element)
checkParameterValid(val.first); checkParameterValid(val.first);
@ -100,6 +103,19 @@ void Whiskers::checkParameterUnknown(string const& _parameter) const
); );
} }
void Whiskers::checkTemplateContainsTags(string const& _parameter, vector<string> 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 namespace
{ {
template<class ReplaceCallback> template<class ReplaceCallback>

View File

@ -73,7 +73,7 @@ public:
using StringMap = std::map<std::string, std::string>; using StringMap = std::map<std::string, std::string>;
using StringListMap = std::map<std::string, std::vector<StringMap>>; using StringListMap = std::map<std::string, std::vector<StringMap>>;
explicit Whiskers(std::string _template); explicit Whiskers(std::string _template = "");
/// Sets a single regular parameter, <paramName>. /// Sets a single regular parameter, <paramName>.
Whiskers& operator()(std::string _parameter, std::string _value); Whiskers& operator()(std::string _parameter, std::string _value);
@ -94,6 +94,12 @@ private:
void checkParameterValid(std::string const& _parameter) const; void checkParameterValid(std::string const& _parameter) const;
void checkParameterUnknown(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<std::string> const& _prefixes) const;
static std::string replace( static std::string replace(
std::string const& _template, std::string const& _template,
StringMap const& _parameters, StringMap const& _parameters,

View File

@ -190,7 +190,7 @@ BOOST_AUTO_TEST_CASE(parameter_collision)
vector<map<string, string>> list(1); vector<map<string, string>> list(1);
list[0]["a"] = "x"; list[0]["a"] = "x";
Whiskers m(templ); Whiskers m(templ);
m("a", "X")("b", list); BOOST_CHECK_THROW(m("a", "X")("b", list), WhiskersError);
BOOST_CHECK_THROW(m.render(), WhiskersError); BOOST_CHECK_THROW(m.render(), WhiskersError);
} }