mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge 4aca2abcb3
into fe1f9c640e
This commit is contained in:
commit
188f5d89ad
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
* String routines
|
* String routines
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <libsolutil/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;
|
||||||
|
}
|
||||||
|
@ -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).
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"language": "Solidity",
|
||||||
|
"sources": {
|
||||||
|
"A": {
|
||||||
|
"content": "
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
pragma solidity >=0.0;
|
||||||
|
|
||||||
|
library L {
|
||||||
|
function f() external {}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract C {
|
||||||
|
function foo() public {
|
||||||
|
L.f();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"libraries": {
|
||||||
|
"A": {
|
||||||
|
"L": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputSelection": {
|
||||||
|
"*": {
|
||||||
|
"C": ["evm.bytecode.object", "evm.bytecode.linkReferences"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"errors":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"component": "general",
|
||||||
|
"formattedMessage": "Library address is not prefixed with \"0x\".",
|
||||||
|
"message": "Library address is not prefixed with \"0x\".",
|
||||||
|
"severity": "error",
|
||||||
|
"type": "JSONError"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"language": "Solidity",
|
||||||
|
"sources": {
|
||||||
|
"A": {
|
||||||
|
"content": "
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
pragma solidity >=0.0;
|
||||||
|
|
||||||
|
library L {
|
||||||
|
function f() external {}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract C {
|
||||||
|
function foo() public {
|
||||||
|
L.f();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"libraries": {
|
||||||
|
"A": {
|
||||||
|
"L": "0x123456789012345678901234567890123456789T"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputSelection": {
|
||||||
|
"*": {
|
||||||
|
"C": ["evm.bytecode.object", "evm.bytecode.linkReferences"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"errors":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"component": "general",
|
||||||
|
"formattedMessage": "Invalid library address (\"0x123456789012345678901234567890123456789T\") supplied.",
|
||||||
|
"message": "Invalid library address (\"0x123456789012345678901234567890123456789T\") supplied.",
|
||||||
|
"severity": "error",
|
||||||
|
"type": "JSONError"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"language": "Solidity",
|
||||||
|
"sources": {
|
||||||
|
"A": {
|
||||||
|
"content": "
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
pragma solidity >=0.0;
|
||||||
|
|
||||||
|
library L {
|
||||||
|
function f() external {}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract C {
|
||||||
|
function foo() public {
|
||||||
|
L.f();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"libraries": {
|
||||||
|
"A": {
|
||||||
|
"L": "0x2323232232323"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputSelection": {
|
||||||
|
"*": {
|
||||||
|
"C": ["evm.bytecode.object", "evm.bytecode.linkReferences"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"errors":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"component": "general",
|
||||||
|
"formattedMessage": "Library address is of invalid length.",
|
||||||
|
"message": "Library address is of invalid length.",
|
||||||
|
"severity": "error",
|
||||||
|
"type": "JSONError"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -399,6 +399,76 @@ BOOST_AUTO_TEST_CASE(standard_json_mode_options)
|
|||||||
BOOST_TEST(parsedOptions == expectedOptions);
|
BOOST_TEST(parsedOptions == expectedOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(invalid_library_address_length)
|
||||||
|
{
|
||||||
|
vector<string> commandLine = {
|
||||||
|
"solc",
|
||||||
|
"contract.sol",
|
||||||
|
"--libraries="
|
||||||
|
"dir1/file1.sol:L=0x"
|
||||||
|
};
|
||||||
|
|
||||||
|
string expectedMessage = "Invalid length for address for library \"dir1/file1.sol:L\": 0 instead of 40 characters.";
|
||||||
|
auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) {
|
||||||
|
return _exception.what() == expectedMessage;
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_CHECK_EXCEPTION(parseCommandLine(commandLine), CommandLineValidationError, hasCorrectMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(invalid_library_address_empty)
|
||||||
|
{
|
||||||
|
vector<string> commandLine = {
|
||||||
|
"solc",
|
||||||
|
"contract.sol",
|
||||||
|
"--libraries="
|
||||||
|
"dir1/file1.sol:L="
|
||||||
|
};
|
||||||
|
|
||||||
|
string expectedMessage = "Empty address provided for library \"dir1/file1.sol:L\".\n"
|
||||||
|
"Note that there should not be any whitespace after the equal sign." ;
|
||||||
|
auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) {
|
||||||
|
return _exception.what() == expectedMessage;
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_CHECK_EXCEPTION(parseCommandLine(commandLine), CommandLineValidationError, hasCorrectMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(invalid_library_address_prefix)
|
||||||
|
{
|
||||||
|
vector<string> commandLine = {
|
||||||
|
"solc",
|
||||||
|
"contract.sol",
|
||||||
|
"--libraries="
|
||||||
|
"dir1/file1.sol:L=1111122222333334444455555666667777788888"
|
||||||
|
};
|
||||||
|
|
||||||
|
string expectedMessage = "The address 1111122222333334444455555666667777788888 is not prefixed with \"0x\".\n"
|
||||||
|
"Note that the address must be prefixed with \"0x\"." ;
|
||||||
|
auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) {
|
||||||
|
return _exception.what() == expectedMessage;
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_CHECK_EXCEPTION(parseCommandLine(commandLine), CommandLineValidationError, hasCorrectMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(invalid_library_address_checksum)
|
||||||
|
{
|
||||||
|
vector<string> commandLine = {
|
||||||
|
"solc",
|
||||||
|
"contract.sol",
|
||||||
|
"--libraries="
|
||||||
|
"dir1/file1.sol:L=0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaaa"
|
||||||
|
};
|
||||||
|
|
||||||
|
string expectedMessage = "Invalid checksum on address for library \"dir1/file1.sol:L\": aAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaaa\n"
|
||||||
|
"The correct checksum is 0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa";
|
||||||
|
auto hasCorrectMessage
|
||||||
|
= [&](CommandLineValidationError const& _exception) { return _exception.what() == expectedMessage; };
|
||||||
|
|
||||||
|
BOOST_CHECK_EXCEPTION(parseCommandLine(commandLine), CommandLineValidationError, hasCorrectMessage);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(invalid_options_input_modes_combinations)
|
BOOST_AUTO_TEST_CASE(invalid_options_input_modes_combinations)
|
||||||
{
|
{
|
||||||
map<string, vector<string>> invalidOptionInputModeCombinations = {
|
map<string, vector<string>> invalidOptionInputModeCombinations = {
|
||||||
|
Loading…
Reference in New Issue
Block a user