unify libraries' address verification

This commit is contained in:
ssi91 2023-08-26 18:37:31 -04:00
parent e9365e93fc
commit 01128d6c16
4 changed files with 73 additions and 26 deletions

View File

@ -881,29 +881,31 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
if (!jsonSourceName[library].isString()) if (!jsonSourceName[library].isString())
return formatFatalError(Error::Type::JSONError, "Library address must be a string."); return formatFatalError(Error::Type::JSONError, "Library address must be a string.");
std::string address = jsonSourceName[library].asString(); std::string address = jsonSourceName[library].asString();
util::h160 addr;
if (!boost::starts_with(address, "0x")) util::ValidationError error = util::validateAddress(address, addr);
switch (error)
{
case util::ValidationError::emptyAddress:
case util::ValidationError::wrongPrefix:
return formatFatalError( return formatFatalError(
Error::Type::JSONError, Error::Type::JSONError,
"Library address is not prefixed with \"0x\"." "Library address is not prefixed with \"0x\"."
); );
case util::ValidationError::wrongAddressLength:
if (address.length() != 42)
return formatFatalError( return formatFatalError(
Error::Type::JSONError, Error::Type::JSONError,
"Library address is of invalid length." "Library address is of invalid length."
); );
case util::ValidationError::checksumNotPassed:
try case util::ValidationError::invalidAddress:
{
ret.libraries[sourceName + ":" + library] = util::h160(address);
}
catch (util::BadHexCharacter const&)
{
return formatFatalError( return formatFatalError(
Error::Type::JSONError, Error::Type::JSONError,
"Invalid library address (\"" + address + "\") supplied." "Invalid library address (\"0x" + address + "\") supplied."
); );
case util::ValidationError::noError:
ret.libraries[sourceName + ":" + library] = addr;
} }
} }
} }

View File

@ -22,6 +22,7 @@
* String routines * String routines
*/ */
#include "FixedHash.h"
#include <libsolutil/StringUtils.h> #include <libsolutil/StringUtils.h>
#include <string> #include <string>
#include <vector> #include <vector>
@ -190,3 +191,26 @@ std::string solidity::util::formatNumberReadable(bigint const& _value, bool _use
return sign + str; return sign + str;
} }
ValidationError solidity::util::validateAddress(std::string& addrString, util::h160& address)
{
if (addrString.empty())
return ValidationError::emptyAddress;
if (addrString.substr(0, 2) != "0x")
return ValidationError::wrongPrefix;
addrString = addrString.substr(2);
if (addrString.length() != 40)
return ValidationError::wrongAddressLength;
if (!util::passesAddressChecksum(addrString, false))
return ValidationError::checksumNotPassed;
bytes binAddr = util::fromHex(addrString);
address = util::h160(binAddr, util::h160::AlignRight);
if (binAddr.size() > 20 || address == util::h160())
return ValidationError::invalidAddress;
return ValidationError::noError;
}

View File

@ -26,6 +26,7 @@
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
#include <libsolutil/Numeric.h> #include <libsolutil/Numeric.h>
#include <libsolutil/FixedHash.h>
#include <fmt/format.h> #include <fmt/format.h>
@ -115,6 +116,17 @@ std::string joinHumanReadablePrefixed
/// @example formatNumberReadable(-57896044618658097711785492504343953926634992332820282019728792003956564819968) = -2**255 /// @example formatNumberReadable(-57896044618658097711785492504343953926634992332820282019728792003956564819968) = -2**255
std::string formatNumberReadable(bigint const& _value, bool _useTruncation = false); std::string formatNumberReadable(bigint const& _value, bool _useTruncation = false);
enum ValidationError {
noError = 0,
emptyAddress,
wrongPrefix,
wrongAddressLength,
checksumNotPassed,
invalidAddress
};
ValidationError validateAddress(std::string& addrString, util::h160& address);
/// Safely converts an unsigned integer as string into an unsigned int type. /// Safely converts an unsigned integer as string into an unsigned int type.
/// ///
/// @return the converted number or nullopt in case of an failure (including if it would not fit). /// @return the converted number or nullopt in case of an failure (including if it would not fit).

View File

@ -23,6 +23,7 @@
#include <libyul/optimiser/Suite.h> #include <libyul/optimiser/Suite.h>
#include <liblangutil/EVMVersion.h> #include <liblangutil/EVMVersion.h>
#include <libsolutil/StringUtils.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
@ -411,43 +412,51 @@ void CommandLineParser::parseLibraryOption(std::string const& _input)
std::string addrString(lib.begin() + static_cast<ptrdiff_t>(separator) + 1, lib.end()); std::string addrString(lib.begin() + static_cast<ptrdiff_t>(separator) + 1, lib.end());
boost::trim(addrString); boost::trim(addrString);
if (addrString.empty())
util::h160 address;
util::ValidationError error = util::validateAddress(addrString, address);
switch (error)
{
case util::ValidationError::emptyAddress:
solThrow( solThrow(
CommandLineValidationError, CommandLineValidationError,
"Empty address provided for library \"" + libName + "\".\n" "Empty address provided for library \"" + libName + "\".\n"
"Note that there should not be any whitespace after the " + "Note that there should not be any whitespace after the " +
(isSeparatorEqualSign ? "equal sign" : "colon") + "." (isSeparatorEqualSign ? "equal sign" : "colon") + "."
); );
break;
if (addrString.substr(0, 2) == "0x") case util::ValidationError::wrongPrefix:
addrString = addrString.substr(2);
else
solThrow( solThrow(
CommandLineValidationError, CommandLineValidationError,
"The address " + addrString + " is not prefixed with \"0x\".\n" "The address " + addrString + " is not prefixed with \"0x\".\n"
"Note that the address must be prefixed with \"0x\"." "Note that the address must be prefixed with \"0x\"."
); );
break;
if (addrString.length() != 40) case util::ValidationError::wrongAddressLength:
solThrow( solThrow(
CommandLineValidationError, CommandLineValidationError,
"Invalid length for address for library \"" + libName + "\": " + "Invalid length for address for library \"" + libName + "\": " +
std::to_string(addrString.length()) + " instead of 40 characters." std::to_string(addrString.length()) + " instead of 40 characters."
); );
if (!util::passesAddressChecksum(addrString, false)) break;
case util::ValidationError::checksumNotPassed:
solThrow( solThrow(
CommandLineValidationError, CommandLineValidationError,
"Invalid checksum on address for library \"" + libName + "\": " + addrString + "\n" "Invalid checksum on address for library \"" + libName + "\": " + addrString + "\n"
"The correct checksum is " + util::getChecksummedAddress(addrString) "The correct checksum is " + util::getChecksummedAddress(addrString)
); );
bytes binAddr = util::fromHex(addrString); break;
util::h160 address(binAddr, util::h160::AlignRight); case util::ValidationError::invalidAddress:
if (binAddr.size() > 20 || address == util::h160())
solThrow( solThrow(
CommandLineValidationError, CommandLineValidationError,
"Invalid address for library \"" + libName + "\": " + addrString "Invalid address for library \"" + libName + "\": " + addrString
); );
m_options.linker.libraries[libName] = address; break;
case util::ValidationError::noError:
m_options.linker.libraries[libName] = address;
break;
}
} }
} }