mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Use hash for library placeholders.
This commit is contained in:
parent
5f5dc8956d
commit
6daeb39ecc
@ -17,6 +17,7 @@ Breaking Changes:
|
|||||||
* Commandline interface: Remove obsolete ``--formal`` option.
|
* Commandline interface: Remove obsolete ``--formal`` option.
|
||||||
* Commandline interface: Rename the ``--julia`` option to ``--yul``.
|
* Commandline interface: Rename the ``--julia`` option to ``--yul``.
|
||||||
* Commandline interface: Require ``-`` if standard input is used as source.
|
* 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.
|
* Compiler interface: Disallow remappings with empty prefix.
|
||||||
* Control Flow Analyzer: Consider mappings as well when checking for uninitialized return values.
|
* 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.
|
* Control Flow Analyzer: Turn warning about returning uninitialized storage pointers into an error.
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <libevmasm/LinkerObject.h>
|
#include <libevmasm/LinkerObject.h>
|
||||||
#include <libdevcore/CommonData.h>
|
#include <libdevcore/CommonData.h>
|
||||||
|
#include <libdevcore/SHA3.h>
|
||||||
|
|
||||||
using namespace dev;
|
using namespace dev;
|
||||||
using namespace dev::eth;
|
using namespace dev::eth;
|
||||||
@ -50,14 +51,19 @@ string LinkerObject::toHex() const
|
|||||||
for (auto const& ref: linkReferences)
|
for (auto const& ref: linkReferences)
|
||||||
{
|
{
|
||||||
size_t pos = ref.first * 2;
|
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] = '_';
|
hex[pos] = hex[pos + 1] = hex[pos + 38] = hex[pos + 39] = '_';
|
||||||
for (size_t i = 0; i < 36; ++i)
|
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;
|
return hex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string LinkerObject::libraryPlaceholder(string const& _libraryName)
|
||||||
|
{
|
||||||
|
return keccak256(_libraryName).hex().substr(0, 36);
|
||||||
|
}
|
||||||
|
|
||||||
h160 const*
|
h160 const*
|
||||||
LinkerObject::matchLibrary(
|
LinkerObject::matchLibrary(
|
||||||
string const& _linkRefName,
|
string const& _linkRefName,
|
||||||
|
@ -50,6 +50,11 @@ struct LinkerObject
|
|||||||
/// addresses by placeholders.
|
/// addresses by placeholders.
|
||||||
std::string toHex() const;
|
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:
|
private:
|
||||||
static h160 const* matchLibrary(
|
static h160 const* matchLibrary(
|
||||||
std::string const& _linkRefName,
|
std::string const& _linkRefName,
|
||||||
|
@ -226,21 +226,21 @@ void CommandLineInterface::handleBinary(string const& _contract)
|
|||||||
if (m_args.count(g_argBinary))
|
if (m_args.count(g_argBinary))
|
||||||
{
|
{
|
||||||
if (m_args.count(g_argOutputDir))
|
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
|
else
|
||||||
{
|
{
|
||||||
cout << "Binary: " << endl;
|
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_argBinaryRuntime))
|
||||||
{
|
{
|
||||||
if (m_args.count(g_argOutputDir))
|
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
|
else
|
||||||
{
|
{
|
||||||
cout << "Binary of the runtime part: " << endl;
|
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;
|
string const& name = library.first;
|
||||||
// Library placeholders are 40 hex digits (20 bytes) that start and end with '__'.
|
// 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
|
// This leaves 36 characters for the library identifier. The identifier used to
|
||||||
// padded on the right with '_' and too long names are truncated.
|
// 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 = "__";
|
string replacement = "__";
|
||||||
for (size_t i = 0; i < placeholderSize - 4; ++i)
|
for (size_t i = 0; i < placeholderSize - 4; ++i)
|
||||||
replacement.push_back(i < name.size() ? name[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;
|
cerr << "Reference \"" << name << "\" in file \"" << src.first << "\" still unresolved." << endl;
|
||||||
it += placeholderSize;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1100,6 +1109,23 @@ void CommandLineInterface::writeLinkedFiles()
|
|||||||
writeFile(src.first, src.second);
|
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(
|
bool CommandLineInterface::assemble(
|
||||||
AssemblyStack::Language _language,
|
AssemblyStack::Language _language,
|
||||||
AssemblyStack::Machine _targetMachine
|
AssemblyStack::Machine _targetMachine
|
||||||
|
@ -54,6 +54,10 @@ public:
|
|||||||
private:
|
private:
|
||||||
bool link();
|
bool link();
|
||||||
void writeLinkedFiles();
|
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);
|
bool assemble(AssemblyStack::Language _language, AssemblyStack::Machine _targetMachine);
|
||||||
|
|
||||||
|
@ -233,6 +233,24 @@ echo '' | "$SOLC" - --link --libraries a:0x90f20564390eAe531E810af625A22f51385Cd
|
|||||||
printTask "Testing long library names..."
|
printTask "Testing long library names..."
|
||||||
echo '' | "$SOLC" - --link --libraries aveeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerylonglibraryname:0x90f20564390eAe531E810af625A22f51385Cd222 >/dev/null
|
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..."
|
printTask "Testing overwriting files..."
|
||||||
SOLTMPDIR=$(mktemp -d)
|
SOLTMPDIR=$(mktemp -d)
|
||||||
(
|
(
|
||||||
|
@ -94,7 +94,7 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(
|
BOOST_CHECK_EQUAL(
|
||||||
_assembly.assemble().toHex(),
|
_assembly.assemble().toHex(),
|
||||||
"5b6001600220606773__someLibrary___________________________"
|
"5b6001600220606773__bf005014d9d0f534b8fcb268bd84c491a238__"
|
||||||
"6000567f556e75736564206665617475726520666f722070757368696e"
|
"6000567f556e75736564206665617475726520666f722070757368696e"
|
||||||
"6720737472696e605f6001605e73000000000000000000000000000000000000000000fe"
|
"6720737472696e605f6001605e73000000000000000000000000000000000000000000fe"
|
||||||
"fe010203044266eeaa"
|
"fe010203044266eeaa"
|
||||||
|
Loading…
Reference in New Issue
Block a user