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/docs/grammar/SolidityLexer.g4 b/docs/grammar/SolidityLexer.g4 index c70a99d91..1549e26e4 100644 --- a/docs/grammar/SolidityLexer.g4 +++ b/docs/grammar/SolidityLexer.g4 @@ -33,7 +33,7 @@ Event: 'event'; External: 'external'; Fallback: 'fallback'; False: 'false'; -Fixed: 'fixed' | ('fixed' [0-9]+ 'x' [0-9]+); +Fixed: 'fixed' | ('fixed' [1-9][0-9]* 'x' [1-9][0-9]*); From: 'from'; /** * Bytes types of fixed length. @@ -86,7 +86,7 @@ Struct: 'struct'; True: 'true'; Try: 'try'; Type: 'type'; -Ufixed: 'ufixed' | ('ufixed' [0-9]+ 'x' [0-9]+); +Ufixed: 'ufixed' | ('ufixed' [1-9][0-9]+ 'x' [1-9][0-9]+); /** * Sized unsigned integer types. * uint is an alias of uint256. 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 new file mode 100644 index 000000000..563778d7e --- /dev/null +++ b/test/libsolidity/syntaxTests/types/weird_sized_types.sol @@ -0,0 +1,42 @@ +contract C { + uint bytes01 = 0; + uint bytes000000001 = 0; + uint bytes000099000 = 0; + uint bytes0a = 0; + + uint int0 = 0; + uint int01 = 0; + uint int000000001 = 0; + uint int000099000 = 0; + uint int0a = 0; + + uint uint0 = 0; + uint uint01 = 0; + uint uint000000001 = 0; + uint uint000099000 = 0; + uint uint0a = 0; + + uint fixed0x0 = 0; + uint fixed01x1 = 0; + uint fixed1x01 = 0; + uint fixed000000001x1 = 0; + uint fixed1x000000001 = 0; + uint fixed000099000x1 = 0; + uint fixed1x000099000 = 0; + uint fixed0ax1 = 0; + uint fixed1x0a = 0; + + uint ufixed0x0 = 0; + uint ufixed01x1 = 0; + uint ufixed1x01 = 0; + uint ufixed000000001x1 = 0; + uint ufixed1x000000001 = 0; + uint ufixed000099000x1 = 0; + uint ufixed1x000099000 = 0; + uint ufixed0ax1 = 0; + uint ufixed1x0a = 0; + + // overflow check + uint uint300 = 0; +} +// ----