aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdevcore/CommonData.cpp40
-rw-r--r--libdevcore/CommonData.h5
-rw-r--r--libsolidity/ast/AST.cpp22
-rw-r--r--solc/CommandLineInterface.cpp5
4 files changed, 49 insertions, 23 deletions
diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp
index 062d1b29..a53d9628 100644
--- a/libdevcore/CommonData.cpp
+++ b/libdevcore/CommonData.cpp
@@ -19,8 +19,12 @@
* @date 2014
*/
-#include "CommonData.h"
-#include "Exceptions.h"
+#include <libdevcore/CommonData.h>
+#include <libdevcore/Exceptions.h>
+#include <libdevcore/SHA3.h>
+
+#include <boost/algorithm/string.hpp>
+
using namespace std;
using namespace dev;
@@ -95,3 +99,35 @@ bytes dev::fromHex(std::string const& _s, WhenError _throw)
}
return ret;
}
+
+
+bool dev::passesAddressChecksum(string const& _str, bool _strict)
+{
+ string s = _str.substr(0, 2) == "0x" ? _str.substr(2) : _str;
+
+ if (s.length() != 40)
+ return false;
+
+ if (!_strict && (
+ _str.find_first_of("abcdef") == string::npos ||
+ _str.find_first_of("ABCDEF") == string::npos
+ ))
+ return true;
+
+ h256 hash = keccak256(boost::algorithm::to_lower_copy(s, std::locale::classic()));
+ for (size_t i = 0; i < 40; ++i)
+ {
+ char addressCharacter = s[i];
+ bool lowerCase;
+ if ('a' <= addressCharacter && addressCharacter <= 'f')
+ lowerCase = true;
+ else if ('A' <= addressCharacter && addressCharacter <= 'F')
+ lowerCase = false;
+ else
+ continue;
+ unsigned nibble = (unsigned(hash[i / 2]) >> (4 * (1 - (i % 2)))) & 0xf;
+ if ((nibble >= 8) == lowerCase)
+ return false;
+ }
+ return true;
+}
diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h
index 5ffcdcca..e0a6d221 100644
--- a/libdevcore/CommonData.h
+++ b/libdevcore/CommonData.h
@@ -179,4 +179,9 @@ bool contains(T const& _t, V const& _v)
return std::end(_t) != std::find(std::begin(_t), std::end(_t), _v);
}
+/// @returns true iff @a _str passess the hex address checksum test.
+/// @param _strict if false, hex strings with only uppercase or only lowercase letters
+/// are considered valid.
+bool passesAddressChecksum(std::string const& _str, bool _strict);
+
}
diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp
index e2b50dd7..616de54e 100644
--- a/libsolidity/ast/AST.cpp
+++ b/libsolidity/ast/AST.cpp
@@ -539,25 +539,5 @@ bool Literal::passesAddressChecksum() const
{
string lit = value();
solAssert(lit.substr(0, 2) == "0x", "Expected hex prefix");
- lit = lit.substr(2);
-
- if (lit.length() != 40)
- return false;
-
- h256 hash = keccak256(boost::algorithm::to_lower_copy(lit, std::locale::classic()));
- for (size_t i = 0; i < 40; ++i)
- {
- char addressCharacter = lit[i];
- bool lowerCase;
- if ('a' <= addressCharacter && addressCharacter <= 'f')
- lowerCase = true;
- else if ('A' <= addressCharacter && addressCharacter <= 'F')
- lowerCase = false;
- else
- continue;
- unsigned nibble = (unsigned(hash[i / 2]) >> (4 * (1 - (i % 2)))) & 0xf;
- if ((nibble >= 8) == lowerCase)
- return false;
- }
- return true;
+ return dev::passesAddressChecksum(lit, true);
}
diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp
index e49e8517..b3ffa6bb 100644
--- a/solc/CommandLineInterface.cpp
+++ b/solc/CommandLineInterface.cpp
@@ -432,6 +432,11 @@ bool CommandLineInterface::parseLibraryOption(string const& _input)
string addrString(lib.begin() + colon + 1, lib.end());
boost::trim(libName);
boost::trim(addrString);
+ if (!passesAddressChecksum(addrString, false))
+ {
+ cerr << "Invalid checksum on library address \"" << libName << "\": " << addrString << endl;
+ return false;
+ }
bytes binAddr = fromHex(addrString);
h160 address(binAddr, h160::AlignRight);
if (binAddr.size() > 20 || address == h160())