diff options
author | Damien George <damien.p.george@gmail.com> | 2014-05-28 14:51:12 +0100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2014-05-28 14:51:12 +0100 |
commit | d1e355ea8e2a5a17ee126f5c3d173b2e6f33e460 (patch) | |
tree | d5ba59452f72a9dcc31fc6cdcf0ad8c08c8713b2 /py/parse.c | |
parent | 813ed3bda6818bd8dd15ee5e3c673a24321e740b (diff) | |
download | micropython-d1e355ea8e2a5a17ee126f5c3d173b2e6f33e460.tar.gz micropython-d1e355ea8e2a5a17ee126f5c3d173b2e6f33e460.zip |
py: Fix check of small-int overflow when parsing ints.
Also unifies use of SMALL_INT_FITS macro across parser and runtime.
Diffstat (limited to 'py/parse.c')
-rw-r--r-- | py/parse.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/py/parse.c b/py/parse.c index 93bced843b..af09c335f2 100644 --- a/py/parse.c +++ b/py/parse.c @@ -36,6 +36,7 @@ #include "lexer.h" #include "parsenumbase.h" #include "parse.h" +#include "smallint.h" #define RULE_ACT_KIND_MASK (0xf0) #define RULE_ACT_ARG_MASK (0x0f) @@ -311,13 +312,13 @@ STATIC void push_result_token(parser_t *parser, const mp_lexer_t *lex) { int i = mp_parse_num_base(str, len, &base); bool overflow = false; for (; i < len; i++) { - machine_int_t old_val = int_val; + int dig; if (unichar_isdigit(str[i]) && str[i] - '0' < base) { - int_val = base * int_val + str[i] - '0'; + dig = str[i] - '0'; } else if (base == 16 && 'a' <= str[i] && str[i] <= 'f') { - int_val = base * int_val + str[i] - 'a' + 10; + dig = str[i] - 'a' + 10; } else if (base == 16 && 'A' <= str[i] && str[i] <= 'F') { - int_val = base * int_val + str[i] - 'A' + 10; + dig = str[i] - 'A' + 10; } else if (str[i] == '.' || str[i] == 'e' || str[i] == 'E' || str[i] == 'j' || str[i] == 'J') { dec = true; break; @@ -325,17 +326,18 @@ STATIC void push_result_token(parser_t *parser, const mp_lexer_t *lex) { small_int = false; break; } - if (int_val < old_val) { - // If new value became less than previous, it's overflow + // add next digi and check for overflow + if (mp_small_int_mul_overflow(int_val, base)) { overflow = true; - } else if ((old_val ^ int_val) & WORD_MSBIT_HIGH) { - // If signed number changed sign - it's overflow + } + int_val = int_val * base + dig; + if (!MP_SMALL_INT_FITS(int_val)) { overflow = true; } } if (dec) { pn = mp_parse_node_new_leaf(MP_PARSE_NODE_DECIMAL, qstr_from_strn(str, len)); - } else if (small_int && !overflow && MP_PARSE_FITS_SMALL_INT(int_val)) { + } else if (small_int && !overflow && MP_SMALL_INT_FITS(int_val)) { pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, int_val); } else { pn = mp_parse_node_new_leaf(MP_PARSE_NODE_INTEGER, qstr_from_strn(str, len)); |