diff --git a/src/lexer.cpp b/src/lexer.cpp index 5b45d2d1..8dbbffe2 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -509,11 +509,11 @@ IntParsingResult parse_uint(std::string_view text, i64* out, int base){ if(base == 10){ // 10-base 12334 if(text.length() == 0) return IntParsingResult::Failure; + constexpr i64 max_i64 = std::numeric_limits::max(); for(char c : text){ if(c >= '0' && c <= '9'){ - i64 prev_out = *out; + if (*out > (max_i64 - (c - '0')) / 10) return IntParsingResult::Overflow; *out = (*out * 10) + (c - '0'); - if(*out < prev_out) return IntParsingResult::Overflow; }else{ return IntParsingResult::Failure; } @@ -523,11 +523,11 @@ IntParsingResult parse_uint(std::string_view text, i64* out, int base){ // 2-base 0b101010 if(f_startswith_2(text, "0b")) text.remove_prefix(2); if(text.length() == 0) return IntParsingResult::Failure; + constexpr i64 mask = i64{1} << 63; for(char c : text){ if(c == '0' || c == '1'){ - i64 prev_out = *out; + if (*out & mask) return IntParsingResult::Overflow; *out = (*out << 1) | (c - '0'); - if(*out < prev_out) return IntParsingResult::Overflow; }else{ return IntParsingResult::Failure; } @@ -537,11 +537,11 @@ IntParsingResult parse_uint(std::string_view text, i64* out, int base){ // 8-base 0o123 if(f_startswith_2(text, "0o")) text.remove_prefix(2); if(text.length() == 0) return IntParsingResult::Failure; + constexpr i64 mask = i64{7} << 60; for(char c : text){ if(c >= '0' && c <= '7'){ - i64 prev_out = *out; + if (*out & mask) return IntParsingResult::Overflow; *out = (*out << 3) | (c - '0'); - if(*out < prev_out) return IntParsingResult::Overflow; }else{ return IntParsingResult::Failure; } @@ -551,17 +551,15 @@ IntParsingResult parse_uint(std::string_view text, i64* out, int base){ // 16-base 0x123 if(f_startswith_2(text, "0x")) text.remove_prefix(2); if(text.length() == 0) return IntParsingResult::Failure; + constexpr i64 mask = i64{15} << 59; for(char c : text){ - i64 prev_out = *out; + if (*out & mask) return IntParsingResult::Overflow; if(c >= '0' && c <= '9'){ *out = (*out << 4) | (c - '0'); - if(*out < prev_out) return IntParsingResult::Overflow; }else if(c >= 'a' && c <= 'f'){ *out = (*out << 4) | (c - 'a' + 10); - if(*out < prev_out) return IntParsingResult::Overflow; }else if(c >= 'A' && c <= 'F'){ *out = (*out << 4) | (c - 'A' + 10); - if(*out < prev_out) return IntParsingResult::Overflow; }else{ return IntParsingResult::Failure; } diff --git a/tests/01_int.py b/tests/01_int.py index 2c13964c..a19640b3 100644 --- a/tests/01_int.py +++ b/tests/01_int.py @@ -142,7 +142,7 @@ except ZeroDivisionError: assert not 1 < 2 > 3 try: - x = eval("231231312312312312312312312312312312314354657553423345632") + x = eval("0x12345678901234567890") print(f"eval should fail, but got {x!r}") exit(1) except SyntaxError: