mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Fixes #10299 - Common function for library address validation
This commit is contained in:
parent
09038ce4cb
commit
f3e8dfdaca
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include <libevmasm/Disassemble.h>
|
#include <libevmasm/Disassemble.h>
|
||||||
|
|
||||||
|
#include <libsolutil/Address.h>
|
||||||
#include <libsmtutil/Exceptions.h>
|
#include <libsmtutil/Exceptions.h>
|
||||||
|
|
||||||
#include <liblangutil/SourceReferenceFormatter.h>
|
#include <liblangutil/SourceReferenceFormatter.h>
|
||||||
@ -888,31 +889,11 @@ 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.");
|
||||||
string address = jsonSourceName[library].asString();
|
std::string addrString = jsonSourceName[library].asString();
|
||||||
|
util::Result<util::h160> addrResult = util::validateAddress(addrString);
|
||||||
if (!boost::starts_with(address, "0x"))
|
if (!addrResult.message().empty())
|
||||||
return formatFatalError(
|
return formatFatalError(Error::Type::JSONError, addrResult.message());
|
||||||
Error::Type::JSONError,
|
ret.libraries[sourceName + ":" + library] = addrResult.get();
|
||||||
"Library address is not prefixed with \"0x\"."
|
|
||||||
);
|
|
||||||
|
|
||||||
if (address.length() != 42)
|
|
||||||
return formatFatalError(
|
|
||||||
Error::Type::JSONError,
|
|
||||||
"Library address is of invalid length."
|
|
||||||
);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ret.libraries[sourceName + ":" + library] = util::h160(address);
|
|
||||||
}
|
|
||||||
catch (util::BadHexCharacter const&)
|
|
||||||
{
|
|
||||||
return formatFatalError(
|
|
||||||
Error::Type::JSONError,
|
|
||||||
"Invalid library address (\"" + address + "\") supplied."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
73
libsolutil/Address.cpp
Normal file
73
libsolutil/Address.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
This file is part of solidity.
|
||||||
|
|
||||||
|
solidity is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
solidity is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
|
||||||
|
#include <libsolutil/Address.h>
|
||||||
|
#include <libsolutil/Exceptions.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace solidity::util
|
||||||
|
{
|
||||||
|
|
||||||
|
/// @returns a h160 representation of an address string
|
||||||
|
/// or an error message in case the address string is not a valid address
|
||||||
|
Result<h160> validateAddress(string _addrString)
|
||||||
|
{
|
||||||
|
string message;
|
||||||
|
h160 address;
|
||||||
|
|
||||||
|
if (_addrString.substr(0, 2) != "0x")
|
||||||
|
message = "Library address \"" + _addrString + "\" is not prefixed with \"0x\".\n"
|
||||||
|
"Note that the address must be prefixed with \"0x\".";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string addrString = _addrString.substr(2);
|
||||||
|
|
||||||
|
if (addrString.length() != 40)
|
||||||
|
message =
|
||||||
|
"Invalid library address length " +
|
||||||
|
to_string(addrString.length()) +
|
||||||
|
" instead of 40 characters.";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
address = util::h160(_addrString);
|
||||||
|
}
|
||||||
|
catch (util::BadHexCharacter const&)
|
||||||
|
{
|
||||||
|
message = "Invalid library address (\"" + _addrString + "\") supplied.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message.empty())
|
||||||
|
{
|
||||||
|
if (!passesAddressChecksum(addrString, false))
|
||||||
|
message =
|
||||||
|
"Invalid checksum for library address \"" + _addrString + "\".\n"
|
||||||
|
"The correct checksum is \"" + getChecksummedAddress(addrString) + "\".";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!message.empty())
|
||||||
|
return Result<h160>::err(message);
|
||||||
|
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
32
libsolutil/Address.h
Normal file
32
libsolutil/Address.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
This file is part of solidity.
|
||||||
|
|
||||||
|
solidity is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
solidity is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libsolutil/Common.h>
|
||||||
|
#include <libsolutil/Result.h>
|
||||||
|
#include <libsolutil/FixedHash.h>
|
||||||
|
|
||||||
|
namespace solidity::util
|
||||||
|
{
|
||||||
|
|
||||||
|
/// @returns a h160 representation of an address string
|
||||||
|
/// or an error message in case the address string is not a valid address
|
||||||
|
Result<h160> validateAddress(std::string _addrString);
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
set(sources
|
set(sources
|
||||||
|
Address.cpp
|
||||||
|
Address.h
|
||||||
Algorithms.h
|
Algorithms.h
|
||||||
AnsiColorized.h
|
AnsiColorized.h
|
||||||
Assertions.h
|
Assertions.h
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
#include <liblangutil/EVMVersion.h>
|
#include <liblangutil/EVMVersion.h>
|
||||||
|
|
||||||
|
#include <libsolutil/Address.h>
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
#include <range/v3/view/transform.hpp>
|
#include <range/v3/view/transform.hpp>
|
||||||
@ -417,36 +419,10 @@ void CommandLineParser::parseLibraryOption(string const& _input)
|
|||||||
"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") + "."
|
||||||
);
|
);
|
||||||
|
util::Result<util::h160> addrResult = util::validateAddress(addrString);
|
||||||
if (addrString.substr(0, 2) == "0x")
|
if (!addrResult.message().empty())
|
||||||
addrString = addrString.substr(2);
|
solThrow(CommandLineValidationError, "Library \"" + libName + "\": " + addrResult.message());
|
||||||
else
|
m_options.linker.libraries[libName] = addrResult.get();
|
||||||
solThrow(
|
|
||||||
CommandLineValidationError,
|
|
||||||
"The address " + addrString + " is not prefixed with \"0x\".\n"
|
|
||||||
"Note that the address must be prefixed with \"0x\"."
|
|
||||||
);
|
|
||||||
|
|
||||||
if (addrString.length() != 40)
|
|
||||||
solThrow(
|
|
||||||
CommandLineValidationError,
|
|
||||||
"Invalid length for address for library \"" + libName + "\": " +
|
|
||||||
to_string(addrString.length()) + " instead of 40 characters."
|
|
||||||
);
|
|
||||||
if (!util::passesAddressChecksum(addrString, false))
|
|
||||||
solThrow(
|
|
||||||
CommandLineValidationError,
|
|
||||||
"Invalid checksum on address for library \"" + libName + "\": " + addrString + "\n"
|
|
||||||
"The correct checksum is " + util::getChecksummedAddress(addrString)
|
|
||||||
);
|
|
||||||
bytes binAddr = util::fromHex(addrString);
|
|
||||||
util::h160 address(binAddr, util::h160::AlignRight);
|
|
||||||
if (binAddr.size() > 20 || address == util::h160())
|
|
||||||
solThrow(
|
|
||||||
CommandLineValidationError,
|
|
||||||
"Invalid address for library \"" + libName + "\": " + addrString
|
|
||||||
);
|
|
||||||
m_options.linker.libraries[libName] = address;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
test/cmdlineTests/linking_solidity_wrong_references/args
Normal file
1
test/cmdlineTests/linking_solidity_wrong_references/args
Normal file
@ -0,0 +1 @@
|
|||||||
|
--bin --bin-runtime --libraries linking_solidity_wrong_references/input.sol:L=0x12345678901234567890123456789012345678AB linking_solidity_wrong_references/input.sol:L1=0x12345678901234567890123456789012345678Ab linking_solidity_wrong_references/input.sol:L2=0x12345678901234567890123456789012345678A sol:L3=x12345678901234567890123456789012345678AB linking_solidity_wrong_references/input.sol:L4=012345678901234567890123456789012345678AB linking_solidity_wrong_references/input.sol:L5=0x linking_solidity_wrong_references/input.sol:L6=0x0
|
@ -0,0 +1,42 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
pragma solidity >=0.0;
|
||||||
|
|
||||||
|
library L {
|
||||||
|
function f() external {}
|
||||||
|
}
|
||||||
|
|
||||||
|
library L1 {
|
||||||
|
function f() external {}
|
||||||
|
}
|
||||||
|
|
||||||
|
library L2 {
|
||||||
|
function f() external {}
|
||||||
|
}
|
||||||
|
|
||||||
|
library L3 {
|
||||||
|
function f() external {}
|
||||||
|
}
|
||||||
|
|
||||||
|
library L4 {
|
||||||
|
function f() external {}
|
||||||
|
}
|
||||||
|
|
||||||
|
library L5 {
|
||||||
|
function f() external {}
|
||||||
|
}
|
||||||
|
|
||||||
|
library L6 {
|
||||||
|
function f() external {}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract C {
|
||||||
|
function foo() public {
|
||||||
|
L.f();
|
||||||
|
L1.f();
|
||||||
|
L2.f();
|
||||||
|
L3.f();
|
||||||
|
L4.f();
|
||||||
|
L5.f();
|
||||||
|
L6.f();
|
||||||
|
}
|
||||||
|
}
|
62
test/cmdlineTests/linking_solidity_wrong_references/output
Normal file
62
test/cmdlineTests/linking_solidity_wrong_references/output
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
|
||||||
|
======= linking_solidity_wrong_references/input.sol:C =======
|
||||||
|
Binary:
|
||||||
|
<BYTECODE REMOVED>__$58d585080104a63ea16eac081c26fdeb7d$__<BYTECODE REMOVED>__$1618aeda50b2dcc26f161cca5d8e112b6f$__<BYTECODE REMOVED>__$265f2a239eabe0580e9e3f71486a88d62d$__<BYTECODE REMOVED>__$5c806807d1dd49cf7e0831ce4f7c3e225c$__<BYTECODE REMOVED>__$305390516cf3f93dc14e593f5c3a7ccd6a$__<BYTECODE REMOVED>__$23207ce64f0ebdd09636cf18c59a1ef8a8$__<BYTECODE REMOVED>
|
||||||
|
|
||||||
|
// $58d585080104a63ea16eac081c26fdeb7d$ -> linking_solidity_wrong_references/input.sol:L1
|
||||||
|
// $1618aeda50b2dcc26f161cca5d8e112b6f$ -> linking_solidity_wrong_references/input.sol:L2
|
||||||
|
// $265f2a239eabe0580e9e3f71486a88d62d$ -> linking_solidity_wrong_references/input.sol:L3
|
||||||
|
// $5c806807d1dd49cf7e0831ce4f7c3e225c$ -> linking_solidity_wrong_references/input.sol:L4
|
||||||
|
// $305390516cf3f93dc14e593f5c3a7ccd6a$ -> linking_solidity_wrong_references/input.sol:L5
|
||||||
|
// $23207ce64f0ebdd09636cf18c59a1ef8a8$ -> linking_solidity_wrong_references/input.sol:L6
|
||||||
|
Binary of the runtime part:
|
||||||
|
<BYTECODE REMOVED>__$58d585080104a63ea16eac081c26fdeb7d$__<BYTECODE REMOVED>__$1618aeda50b2dcc26f161cca5d8e112b6f$__<BYTECODE REMOVED>__$265f2a239eabe0580e9e3f71486a88d62d$__<BYTECODE REMOVED>__$5c806807d1dd49cf7e0831ce4f7c3e225c$__<BYTECODE REMOVED>__$305390516cf3f93dc14e593f5c3a7ccd6a$__<BYTECODE REMOVED>__$23207ce64f0ebdd09636cf18c59a1ef8a8$__<BYTECODE REMOVED>
|
||||||
|
|
||||||
|
// $58d585080104a63ea16eac081c26fdeb7d$ -> linking_solidity_wrong_references/input.sol:L1
|
||||||
|
// $1618aeda50b2dcc26f161cca5d8e112b6f$ -> linking_solidity_wrong_references/input.sol:L2
|
||||||
|
// $265f2a239eabe0580e9e3f71486a88d62d$ -> linking_solidity_wrong_references/input.sol:L3
|
||||||
|
// $5c806807d1dd49cf7e0831ce4f7c3e225c$ -> linking_solidity_wrong_references/input.sol:L4
|
||||||
|
// $305390516cf3f93dc14e593f5c3a7ccd6a$ -> linking_solidity_wrong_references/input.sol:L5
|
||||||
|
// $23207ce64f0ebdd09636cf18c59a1ef8a8$ -> linking_solidity_wrong_references/input.sol:L6
|
||||||
|
|
||||||
|
======= linking_solidity_wrong_references/input.sol:L =======
|
||||||
|
Binary:
|
||||||
|
<BYTECODE REMOVED>
|
||||||
|
Binary of the runtime part:
|
||||||
|
<BYTECODE REMOVED>
|
||||||
|
|
||||||
|
======= linking_solidity_wrong_references/input.sol:L1 =======
|
||||||
|
Binary:
|
||||||
|
<BYTECODE REMOVED>
|
||||||
|
Binary of the runtime part:
|
||||||
|
<BYTECODE REMOVED>
|
||||||
|
|
||||||
|
======= linking_solidity_wrong_references/input.sol:L2 =======
|
||||||
|
Binary:
|
||||||
|
<BYTECODE REMOVED>
|
||||||
|
Binary of the runtime part:
|
||||||
|
<BYTECODE REMOVED>
|
||||||
|
|
||||||
|
======= linking_solidity_wrong_references/input.sol:L3 =======
|
||||||
|
Binary:
|
||||||
|
<BYTECODE REMOVED>
|
||||||
|
Binary of the runtime part:
|
||||||
|
<BYTECODE REMOVED>
|
||||||
|
|
||||||
|
======= linking_solidity_wrong_references/input.sol:L4 =======
|
||||||
|
Binary:
|
||||||
|
<BYTECODE REMOVED>
|
||||||
|
Binary of the runtime part:
|
||||||
|
<BYTECODE REMOVED>
|
||||||
|
|
||||||
|
======= linking_solidity_wrong_references/input.sol:L5 =======
|
||||||
|
Binary:
|
||||||
|
<BYTECODE REMOVED>
|
||||||
|
Binary of the runtime part:
|
||||||
|
<BYTECODE REMOVED>
|
||||||
|
|
||||||
|
======= linking_solidity_wrong_references/input.sol:L6 =======
|
||||||
|
Binary:
|
||||||
|
<BYTECODE REMOVED>
|
||||||
|
Binary of the runtime part:
|
||||||
|
<BYTECODE REMOVED>
|
@ -853,7 +853,7 @@ BOOST_AUTO_TEST_CASE(libraries_invalid_length)
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
Json::Value result = compile(input);
|
Json::Value result = compile(input);
|
||||||
BOOST_CHECK(containsError(result, "JSONError", "Library address is of invalid length."));
|
BOOST_CHECK(containsError(result, "JSONError", "Invalid library address length 2 instead of 40 characters."));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(libraries_missing_hex_prefix)
|
BOOST_AUTO_TEST_CASE(libraries_missing_hex_prefix)
|
||||||
@ -876,7 +876,32 @@ BOOST_AUTO_TEST_CASE(libraries_missing_hex_prefix)
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
Json::Value result = compile(input);
|
Json::Value result = compile(input);
|
||||||
BOOST_CHECK(containsError(result, "JSONError", "Library address is not prefixed with \"0x\"."));
|
BOOST_CHECK(containsError(result, "JSONError",
|
||||||
|
"Library address \"4200000000000000000000000000000000000001\" is not prefixed with \"0x\".\nNote that the address must be prefixed with \"0x\"."));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(libraries_invalid_ckecsum)
|
||||||
|
{
|
||||||
|
char const* input = R"(
|
||||||
|
{
|
||||||
|
"language": "Solidity",
|
||||||
|
"settings": {
|
||||||
|
"libraries": {
|
||||||
|
"library.sol": {
|
||||||
|
"L": "0x42000000000000000000000000000000000000Ab"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sources": {
|
||||||
|
"empty": {
|
||||||
|
"content": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
Json::Value result = compile(input);
|
||||||
|
BOOST_CHECK(containsError(result, "JSONError",
|
||||||
|
"Invalid checksum for library address \"0x42000000000000000000000000000000000000Ab\".\nThe correct checksum is \"0x42000000000000000000000000000000000000AB\"."));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(library_linking)
|
BOOST_AUTO_TEST_CASE(library_linking)
|
||||||
|
Loading…
Reference in New Issue
Block a user