aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md1
-rw-r--r--libevmasm/LinkerObject.cpp10
-rw-r--r--libevmasm/LinkerObject.h5
-rw-r--r--solc/CommandLineInterface.cpp38
-rw-r--r--solc/CommandLineInterface.h4
-rwxr-xr-xtest/cmdlineTests.sh18
-rw-r--r--test/libevmasm/Assembler.cpp2
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"