mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-23 04:50:17 +00:00
raise error on literal ints overflow
This commit is contained in:
parent
e3fa25d774
commit
7f7e1a14ee
@ -136,6 +136,13 @@ struct Lexer {
|
|||||||
std::vector<Token> run();
|
std::vector<Token> run();
|
||||||
};
|
};
|
||||||
|
|
||||||
bool parse_int(std::string_view text, i64* out, int base);
|
|
||||||
|
enum class IntParsingResult{
|
||||||
|
Success,
|
||||||
|
Failure,
|
||||||
|
Overflow,
|
||||||
|
};
|
||||||
|
|
||||||
|
IntParsingResult parse_int(std::string_view text, i64* out, int base);
|
||||||
|
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
||||||
|
@ -284,9 +284,15 @@ static bool is_unicode_Lo_char(uint32_t c) {
|
|||||||
}
|
}
|
||||||
// try integer
|
// try integer
|
||||||
i64 int_out;
|
i64 int_out;
|
||||||
if(parse_int(text, &int_out, -1)){
|
switch(parse_int(text, &int_out, -1)){
|
||||||
add_token(TK("@num"), int_out);
|
case IntParsingResult::Success:
|
||||||
return;
|
add_token(TK("@num"), int_out);
|
||||||
|
return;
|
||||||
|
case IntParsingResult::Overflow:
|
||||||
|
SyntaxError("integer literal too large");
|
||||||
|
return;
|
||||||
|
case IntParsingResult::Failure:
|
||||||
|
break; // do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -476,7 +482,7 @@ static bool is_unicode_Lo_char(uint32_t c) {
|
|||||||
return std::move(nexts);
|
return std::move(nexts);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse_int(std::string_view text, i64* out, int base){
|
IntParsingResult parse_int(std::string_view text, i64* out, int base){
|
||||||
*out = 0;
|
*out = 0;
|
||||||
|
|
||||||
const auto f_startswith_2 = [](std::string_view t, const char* prefix) -> bool{
|
const auto f_startswith_2 = [](std::string_view t, const char* prefix) -> bool{
|
||||||
@ -493,63 +499,63 @@ bool parse_int(std::string_view text, i64* out, int base){
|
|||||||
|
|
||||||
if(base == 10){
|
if(base == 10){
|
||||||
// 10-base 12334
|
// 10-base 12334
|
||||||
if(text.length() == 0) return false;
|
if(text.length() == 0) return IntParsingResult::Failure;
|
||||||
for(char c : text){
|
for(char c : text){
|
||||||
if(c >= '0' && c <= '9'){
|
if(c >= '0' && c <= '9'){
|
||||||
*out = (*out * 10) + (c - '0');
|
*out = (*out * 10) + (c - '0');
|
||||||
if(*out < 0) return false; // overflow
|
if(*out < 0) return IntParsingResult::Overflow;
|
||||||
}else{
|
}else{
|
||||||
return false;
|
return IntParsingResult::Failure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return IntParsingResult::Success;
|
||||||
}else if(base == 2){
|
}else if(base == 2){
|
||||||
// 2-base 0b101010
|
// 2-base 0b101010
|
||||||
if(f_startswith_2(text, "0b")) text.remove_prefix(2);
|
if(f_startswith_2(text, "0b")) text.remove_prefix(2);
|
||||||
if(text.length() == 0) return false;
|
if(text.length() == 0) return IntParsingResult::Failure;
|
||||||
for(char c : text){
|
for(char c : text){
|
||||||
if(c == '0' || c == '1'){
|
if(c == '0' || c == '1'){
|
||||||
*out = (*out << 1) | (c - '0');
|
*out = (*out << 1) | (c - '0');
|
||||||
if(*out < 0) return false; // overflow
|
if(*out < 0) return IntParsingResult::Overflow;
|
||||||
}else{
|
}else{
|
||||||
return false;
|
return IntParsingResult::Failure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return IntParsingResult::Success;
|
||||||
}else if(base == 8){
|
}else if(base == 8){
|
||||||
// 8-base 0o123
|
// 8-base 0o123
|
||||||
if(f_startswith_2(text, "0o")) text.remove_prefix(2);
|
if(f_startswith_2(text, "0o")) text.remove_prefix(2);
|
||||||
if(text.length() == 0) return false;
|
if(text.length() == 0) return IntParsingResult::Failure;
|
||||||
for(char c : text){
|
for(char c : text){
|
||||||
if(c >= '0' && c <= '7'){
|
if(c >= '0' && c <= '7'){
|
||||||
*out = (*out << 3) | (c - '0');
|
*out = (*out << 3) | (c - '0');
|
||||||
if(*out < 0) return false; // overflow
|
if(*out < 0) return IntParsingResult::Overflow;
|
||||||
}else{
|
}else{
|
||||||
return false;
|
return IntParsingResult::Failure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return IntParsingResult::Success;
|
||||||
}else if(base == 16){
|
}else if(base == 16){
|
||||||
// 16-base 0x123
|
// 16-base 0x123
|
||||||
if(f_startswith_2(text, "0x")) text.remove_prefix(2);
|
if(f_startswith_2(text, "0x")) text.remove_prefix(2);
|
||||||
if(text.length() == 0) return false;
|
if(text.length() == 0) return IntParsingResult::Failure;
|
||||||
for(char c : text){
|
for(char c : text){
|
||||||
if(c >= '0' && c <= '9'){
|
if(c >= '0' && c <= '9'){
|
||||||
*out = (*out << 4) | (c - '0');
|
*out = (*out << 4) | (c - '0');
|
||||||
if(*out < 0) return false; // overflow
|
if(*out < 0) return IntParsingResult::Overflow;
|
||||||
}else if(c >= 'a' && c <= 'f'){
|
}else if(c >= 'a' && c <= 'f'){
|
||||||
*out = (*out << 4) | (c - 'a' + 10);
|
*out = (*out << 4) | (c - 'a' + 10);
|
||||||
if(*out < 0) return false; // overflow
|
if(*out < 0) return IntParsingResult::Overflow;
|
||||||
}else if(c >= 'A' && c <= 'F'){
|
}else if(c >= 'A' && c <= 'F'){
|
||||||
*out = (*out << 4) | (c - 'A' + 10);
|
*out = (*out << 4) | (c - 'A' + 10);
|
||||||
if(*out < 0) return false; // overflow
|
if(*out < 0) return IntParsingResult::Overflow;
|
||||||
}else{
|
}else{
|
||||||
return false;
|
return IntParsingResult::Failure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return IntParsingResult::Success;
|
||||||
}
|
}
|
||||||
return false;
|
return IntParsingResult::Failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
||||||
|
@ -415,7 +415,7 @@ void init_builtins(VM* _vm) {
|
|||||||
sv.remove_prefix(1);
|
sv.remove_prefix(1);
|
||||||
}
|
}
|
||||||
i64 val;
|
i64 val;
|
||||||
if(!parse_int(sv, &val, base)){
|
if(parse_int(sv, &val, base) != IntParsingResult::Success){
|
||||||
vm->ValueError(_S("invalid literal for int() with base ", base, ": ", s.escape()));
|
vm->ValueError(_S("invalid literal for int() with base ", base, ": ", s.escape()));
|
||||||
}
|
}
|
||||||
if(negative) val = -val;
|
if(negative) val = -val;
|
||||||
|
@ -124,3 +124,9 @@ except ZeroDivisionError:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
assert not 1 < 2 > 3
|
assert not 1 < 2 > 3
|
||||||
|
|
||||||
|
try:
|
||||||
|
eval("231231312312312312312312312312312312314354657553423345632")
|
||||||
|
exit(1)
|
||||||
|
except SyntaxError:
|
||||||
|
pass
|
||||||
|
Loading…
x
Reference in New Issue
Block a user