diff --git a/Changelog.md b/Changelog.md index fa01287e4..c9f4d2318 100644 --- a/Changelog.md +++ b/Changelog.md @@ -26,6 +26,7 @@ Bugfixes: * SMTChecker: Fix internal error when trying to generate counterexamples with old z3. * SMTChecker: Fix segmentation fault that could occur on certain SMT-enabled sources when no SMT solver was available. * Type Checker: ``super`` is not available in libraries. + * Type Checker: Disallow leading zeroes in sized-types (e.g. ``bytes000032``), but allow them to be treated as identifiers. * Yul Optimizer: Fix a bug in NameSimplifier where a new name created by NameSimplifier could also be created by NameDispenser. * Yul Optimizer: Removed NameSimplifier from optimization steps available to users. diff --git a/liblangutil/Token.cpp b/liblangutil/Token.cpp index 28180514a..31f1f310e 100644 --- a/liblangutil/Token.cpp +++ b/liblangutil/Token.cpp @@ -41,7 +41,6 @@ // along with solidity. If not, see . #include -#include #include using namespace std; @@ -126,22 +125,6 @@ int precedence(Token tok) } #undef T -namespace -{ -int parseSize(string::const_iterator _begin, string::const_iterator _end) -{ - try - { - int m = boost::lexical_cast(boost::make_iterator_range(_begin, _end)); - return m; - } - catch(boost::bad_lexical_cast const&) - { - return -1; - } -} -} - static Token keywordByName(string const& _name) { // The following macros are used inside TOKEN_LIST and cause non-keyword tokens to be ignored @@ -162,6 +145,32 @@ bool isYulKeyword(string const& _literal) tuple fromIdentifierOrKeyword(string const& _literal) { + // Used for `bytesM`, `uintM`, `intM`, `fixedMxN`, `ufixedMxN`. + // M/N must be shortest representation. M can never be 0. N can be zero. + auto parseSize = [](string::const_iterator _begin, string::const_iterator _end) -> int + { + // No number. + if (distance(_begin, _end) == 0) + return -1; + + // Disallow leading zero. + if (distance(_begin, _end) > 1 && *_begin == '0') + return -1; + + int ret = 0; + for (auto it = _begin; it != _end; it++) + { + if (*it < '0' || *it > '9') + return -1; + // Overflow check. The largest acceptable value is 256 in the callers. + if (ret >= 256) + return -1; + ret *= 10; + ret += *it - '0'; + } + return ret; + }; + auto positionM = find_if(_literal.begin(), _literal.end(), ::isdigit); if (positionM != _literal.end()) { diff --git a/test/libsolidity/syntaxTests/types/weird_sized_types.sol b/test/libsolidity/syntaxTests/types/weird_sized_types.sol index 83f9362e0..563778d7e 100644 --- a/test/libsolidity/syntaxTests/types/weird_sized_types.sol +++ b/test/libsolidity/syntaxTests/types/weird_sized_types.sol @@ -40,4 +40,3 @@ contract C { uint uint300 = 0; } // ---- -// ParserError 2314: (22-29): Expected identifier but got 'bytes1'