diff options
author | chriseth <chris@ethereum.org> | 2018-10-04 20:55:02 +0800 |
---|---|---|
committer | chriseth <chris@ethereum.org> | 2018-10-12 21:15:01 +0800 |
commit | 6daeb39ecc7ffd0e834e63f6495442c4211c5c1c (patch) | |
tree | 670349dc15db2f9be5210f4ad2c99a386c079168 | |
parent | 5f5dc8956d39ab19c5408aa4c39a3cd10d3a2dec (diff) | |
download | dexon-solidity-6daeb39ecc7ffd0e834e63f6495442c4211c5c1c.tar.gz dexon-solidity-6daeb39ecc7ffd0e834e63f6495442c4211c5c1c.tar.zst dexon-solidity-6daeb39ecc7ffd0e834e63f6495442c4211c5c1c.zip |
Use hash for library placeholders.
-rw-r--r-- | Changelog.md | 1 | ||||
-rw-r--r-- | libevmasm/LinkerObject.cpp | 10 | ||||
-rw-r--r-- | libevmasm/LinkerObject.h | 5 | ||||
-rw-r--r-- | solc/CommandLineInterface.cpp | 38 | ||||
-rw-r--r-- | solc/CommandLineInterface.h | 4 | ||||
-rwxr-xr-x | test/cmdlineTests.sh | 18 | ||||
-rw-r--r-- | test/libevmasm/Assembler.cpp | 2 |
7 files changed, 69 insertions, 9 deletions
diff --git a/Changelog.md b/Changelog.md index 86376017..b817dc22 100644 --- a/Changelog.md +++ b/Changelog.md @@ -17,6 +17,7 @@ Breaking Changes: * Commandline interface: Remove obsolete ``--formal`` option. * Commandline interface: Rename the ``--julia`` option to ``--yul``. * Commandline interface: Require ``-`` if standard input is used as source. + * Commandline interface: Use hash of library name for link placeholder instead of name itself. * Compiler interface: Disallow remappings with empty prefix. * Control Flow Analyzer: Consider mappings as well when checking for uninitialized return values. * Control Flow Analyzer: Turn warning about returning uninitialized storage pointers into an error. diff --git a/libevmasm/LinkerObject.cpp b/libevmasm/LinkerObject.cpp index 1d5efecb..0ac69966 100644 --- a/libevmasm/LinkerObject.cpp +++ b/libevmasm/LinkerObject.cpp @@ -21,6 +21,7 @@ #include <libevmasm/LinkerObject.h> #include <libdevcore/CommonData.h> +#include <libdevcore/SHA3.h> using namespace dev; using namespace dev::eth; @@ -50,14 +51,19 @@ string LinkerObject::toHex() const for (auto const& ref: linkReferences) { size_t pos = ref.first * 2; - string const& name = ref.second; + string hash = libraryPlaceholder(ref.second); hex[pos] = hex[pos + 1] = hex[pos + 38] = hex[pos + 39] = '_'; for (size_t i = 0; i < 36; ++i) - hex[pos + 2 + i] = i < name.size() ? name[i] : '_'; + hex[pos + 2 + i] = hash.at(i); } return hex; } +string LinkerObject::libraryPlaceholder(string const& _libraryName) +{ + return keccak256(_libraryName).hex().substr(0, 36); +} + h160 const* LinkerObject::matchLibrary( string const& _linkRefName, diff --git a/libevmasm/LinkerObject.h b/libevmasm/LinkerObject.h index 152487b4..92890803 100644 --- a/libevmasm/LinkerObject.h +++ b/libevmasm/LinkerObject.h @@ -50,6 +50,11 @@ struct LinkerObject /// addresses by placeholders. std::string toHex() const; + /// @returns a 36 character string that is used as a placeholder for the library + /// address (enclosed by `__` on both sides). The placeholder is the hex representation + /// of the first 18 bytes of the keccak-256 hash of @a _libraryName. + static std::string libraryPlaceholder(std::string const& _libraryName); + private: static h160 const* matchLibrary( std::string const& _linkRefName, diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 8fd0d6ef..7ab76c12 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -226,21 +226,21 @@ void CommandLineInterface::handleBinary(string const& _contract) if (m_args.count(g_argBinary)) { if (m_args.count(g_argOutputDir)) - createFile(m_compiler->filesystemFriendlyName(_contract) + ".bin", m_compiler->object(_contract).toHex()); + createFile(m_compiler->filesystemFriendlyName(_contract) + ".bin", objectWithLinkRefsHex(m_compiler->object(_contract))); else { cout << "Binary: " << endl; - cout << m_compiler->object(_contract).toHex() << endl; + cout << objectWithLinkRefsHex(m_compiler->object(_contract)) << endl; } } if (m_args.count(g_argBinaryRuntime)) { if (m_args.count(g_argOutputDir)) - createFile(m_compiler->filesystemFriendlyName(_contract) + ".bin-runtime", m_compiler->runtimeObject(_contract).toHex()); + createFile(m_compiler->filesystemFriendlyName(_contract) + ".bin-runtime", objectWithLinkRefsHex(m_compiler->runtimeObject(_contract))); else { cout << "Binary of the runtime part: " << endl; - cout << m_compiler->runtimeObject(_contract).toHex() << endl; + cout << objectWithLinkRefsHex(m_compiler->runtimeObject(_contract)) << endl; } } } @@ -1056,8 +1056,12 @@ bool CommandLineInterface::link() { string const& name = library.first; // Library placeholders are 40 hex digits (20 bytes) that start and end with '__'. - // This leaves 36 characters for the library name, while too short library names are - // padded on the right with '_' and too long names are truncated. + // This leaves 36 characters for the library identifier. The identifier used to + // be just the cropped or '_'-padded library name, but this changed to + // the cropped hex representation of the hash of the library name. + // We support both ways of linking here. + librariesReplacements["__" + eth::LinkerObject::libraryPlaceholder(name) + "__"] = library.second; + string replacement = "__"; for (size_t i = 0; i < placeholderSize - 4; ++i) replacement.push_back(i < name.size() ? name[i] : '_'); @@ -1087,6 +1091,11 @@ bool CommandLineInterface::link() cerr << "Reference \"" << name << "\" in file \"" << src.first << "\" still unresolved." << endl; it += placeholderSize; } + // Remove hints for resolved libraries. + for (auto const& library: m_libraries) + boost::algorithm::erase_all(src.second, "\n" + libraryPlaceholderHint(library.first)); + while (!src.second.empty() && *prev(src.second.end()) == '\n') + src.second.resize(src.second.size() - 1); } return true; } @@ -1100,6 +1109,23 @@ void CommandLineInterface::writeLinkedFiles() writeFile(src.first, src.second); } +string CommandLineInterface::libraryPlaceholderHint(string const& _libraryName) +{ + return "// " + eth::LinkerObject::libraryPlaceholder(_libraryName) + " -> " + _libraryName; +} + +string CommandLineInterface::objectWithLinkRefsHex(eth::LinkerObject const& _obj) +{ + string out = _obj.toHex(); + if (!_obj.linkReferences.empty()) + { + out += "\n"; + for (auto const& linkRef: _obj.linkReferences) + out += "\n" + libraryPlaceholderHint(linkRef.second); + } + return out; +} + bool CommandLineInterface::assemble( AssemblyStack::Language _language, AssemblyStack::Machine _targetMachine diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index 010dce34..aa49383a 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -54,6 +54,10 @@ public: private: bool link(); void writeLinkedFiles(); + /// @returns the ``// <identifier> -> name`` hint for library placeholders. + static std::string libraryPlaceholderHint(std::string const& _libraryName); + /// @returns the full object with library placeholder hints in hex. + static std::string objectWithLinkRefsHex(eth::LinkerObject const& _obj); bool assemble(AssemblyStack::Language _language, AssemblyStack::Machine _targetMachine); diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index 71866bce..20254ef4 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -233,6 +233,24 @@ echo '' | "$SOLC" - --link --libraries a:0x90f20564390eAe531E810af625A22f51385Cd printTask "Testing long library names..." echo '' | "$SOLC" - --link --libraries aveeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerylonglibraryname:0x90f20564390eAe531E810af625A22f51385Cd222 >/dev/null +printTask "Testing linking itself..." +SOLTMPDIR=$(mktemp -d) +( + cd "$SOLTMPDIR" + set -e + echo 'library L { function f() public pure {} } contract C { function f() public pure { L.f(); } }' > x.sol + "$SOLC" --bin -o . x.sol 2>/dev/null + # Explanation and placeholder should be there + grep -q '//' C.bin && grep -q '__' C.bin + # But not in library file. + grep -q -v '[/_]' L.bin + # Now link + "$SOLC" --link --libraries x.sol:L:0x90f20564390eAe531E810af625A22f51385Cd222 C.bin + # Now the placeholder and explanation should be gone. + grep -q -v '[/_]' C.bin +) +rm -rf "$SOLTMPDIR" + printTask "Testing overwriting files..." SOLTMPDIR=$(mktemp -d) ( diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index bc652f56..38ed9732 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -94,7 +94,7 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) BOOST_CHECK_EQUAL( _assembly.assemble().toHex(), - "5b6001600220606773__someLibrary___________________________" + "5b6001600220606773__bf005014d9d0f534b8fcb268bd84c491a238__" "6000567f556e75736564206665617475726520666f722070757368696e" "6720737472696e605f6001605e73000000000000000000000000000000000000000000fe" "fe010203044266eeaa" |