From 368ea01bb25f835d9221d2b574535c2883f928bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 17 Aug 2023 18:35:20 +0200 Subject: [PATCH 1/3] BytesUtils: Don't introduce garbage when formatting byte vectors shorter than expected --- test/libsolidity/util/BytesUtils.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/test/libsolidity/util/BytesUtils.cpp b/test/libsolidity/util/BytesUtils.cpp index f2a5db7af..47cdc1783 100644 --- a/test/libsolidity/util/BytesUtils.cpp +++ b/test/libsolidity/util/BytesUtils.cpp @@ -26,6 +26,8 @@ #include +#include +#include #include #include #include @@ -253,7 +255,8 @@ std::string BytesUtils::formatFixedPoint(bytes const& _bytes, bool _signed, size string BytesUtils::formatRawBytes( bytes const& _bytes, solidity::frontend::test::ParameterList const& _parameters, - string _linePrefix) + string _linePrefix +) { stringstream os; ParameterList parameters; @@ -263,16 +266,19 @@ string BytesUtils::formatRawBytes( parameters = ContractABIUtils::defaultParameters((_bytes.size() + 31) / 32); else parameters = _parameters; + soltestAssert(ContractABIUtils::encodingSize(parameters) >= _bytes.size()); for (auto const& parameter: parameters) { - bytes byteRange{it, it + static_cast(parameter.abiType.size)}; + long actualSize = min(distance(it, _bytes.end()), static_cast(parameter.abiType.size)); + bytes byteRange(parameter.abiType.size, 0); + copy(it, it + actualSize, byteRange.begin()); os << _linePrefix << byteRange; if (¶meter != ¶meters.back()) os << endl; - it += static_cast(parameter.abiType.size); + it += actualSize; } return os.str(); @@ -368,11 +374,13 @@ string BytesUtils::formatBytesRange( parameters = ContractABIUtils::defaultParameters((_bytes.size() + 31) / 32); else parameters = _parameters; - + soltestAssert(ContractABIUtils::encodingSize(parameters) >= _bytes.size()); for (auto const& parameter: parameters) { - bytes byteRange{it, it + static_cast(parameter.abiType.size)}; + long actualSize = min(distance(it, _bytes.end()), static_cast(parameter.abiType.size)); + bytes byteRange(parameter.abiType.size, 0); + copy(it, it + actualSize, byteRange.begin()); if (!parameter.matchesBytes(byteRange)) AnsiColorized( @@ -386,7 +394,7 @@ string BytesUtils::formatBytesRange( if (¶meter != ¶meters.back()) os << ", "; - it += static_cast(parameter.abiType.size); + it += actualSize; } return os.str(); From 0f5aacefa0bdd2cd7b1fff1f17525e0f240a6c60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 17 Aug 2023 19:52:57 +0200 Subject: [PATCH 2/3] BytesUtils: Don't format parameters shorter than 32 bytes as integers --- test/libsolidity/util/BytesUtils.cpp | 30 ++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/test/libsolidity/util/BytesUtils.cpp b/test/libsolidity/util/BytesUtils.cpp index 47cdc1783..57d7e12c6 100644 --- a/test/libsolidity/util/BytesUtils.cpp +++ b/test/libsolidity/util/BytesUtils.cpp @@ -263,7 +263,20 @@ string BytesUtils::formatRawBytes( auto it = _bytes.begin(); if (_bytes.size() != ContractABIUtils::encodingSize(_parameters)) - parameters = ContractABIUtils::defaultParameters((_bytes.size() + 31) / 32); + { + // Interpret all full 32-byte values as integers. + parameters = ContractABIUtils::defaultParameters(_bytes.size() / 32); + + // We'd introduce trailing zero bytes if we interpreted the final bit as an integer. + // We want a right-aligned sequence of bytes instead. + if (_bytes.size() % 32 != 0) + parameters.push_back({ + bytes(), + "", + ABIType{ABIType::HexString, ABIType::AlignRight, _bytes.size() % 32}, + FormatInfo{}, + }); + } else parameters = _parameters; soltestAssert(ContractABIUtils::encodingSize(parameters) >= _bytes.size()); @@ -371,7 +384,20 @@ string BytesUtils::formatBytesRange( auto it = _bytes.begin(); if (_bytes.size() != ContractABIUtils::encodingSize(_parameters)) - parameters = ContractABIUtils::defaultParameters((_bytes.size() + 31) / 32); + { + // Interpret all full 32-byte values as integers. + parameters = ContractABIUtils::defaultParameters(_bytes.size() / 32); + + // We'd introduce trailing zero bytes if we interpreted the final bit as an integer. + // We want a right-aligned sequence of bytes instead. + if (_bytes.size() % 32 != 0) + parameters.push_back({ + bytes(), + "", + ABIType{ABIType::HexString, ABIType::AlignRight, _bytes.size() % 32}, + FormatInfo{}, + }); + } else parameters = _parameters; soltestAssert(ContractABIUtils::encodingSize(parameters) >= _bytes.size()); From 397a5543a4b8a42cb97d76b76181394abfd69be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 17 Aug 2023 20:45:16 +0200 Subject: [PATCH 3/3] fixup! BytesUtils: Don't introduce garbage when formatting byte vectors shorter than expected --- test/libsolidity/util/BytesUtils.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/libsolidity/util/BytesUtils.cpp b/test/libsolidity/util/BytesUtils.cpp index 57d7e12c6..58d1baacd 100644 --- a/test/libsolidity/util/BytesUtils.cpp +++ b/test/libsolidity/util/BytesUtils.cpp @@ -283,7 +283,10 @@ string BytesUtils::formatRawBytes( for (auto const& parameter: parameters) { - long actualSize = min(distance(it, _bytes.end()), static_cast(parameter.abiType.size)); + long actualSize = min( + distance(it, _bytes.end()), + static_cast(parameter.abiType.size) + ); bytes byteRange(parameter.abiType.size, 0); copy(it, it + actualSize, byteRange.begin()); @@ -404,7 +407,10 @@ string BytesUtils::formatBytesRange( for (auto const& parameter: parameters) { - long actualSize = min(distance(it, _bytes.end()), static_cast(parameter.abiType.size)); + long actualSize = min( + distance(it, _bytes.end()), + static_cast(parameter.abiType.size) + ); bytes byteRange(parameter.abiType.size, 0); copy(it, it + actualSize, byteRange.begin());