-
Notifications
You must be signed in to change notification settings - Fork 218
gccrs: Fix 128-bit non-decimal integer literal saturation #4454
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2239,8 +2239,10 @@ Lexer::parse_raw_string (location_t loc, int initial_hash_count) | |||||||||
| template <typename IsDigitFunc> | ||||||||||
| TokenPtr | ||||||||||
| Lexer::parse_non_decimal_int_literal (location_t loc, IsDigitFunc is_digit_func, | ||||||||||
| std::string existent_str, int base) | ||||||||||
| int base) | ||||||||||
| { | ||||||||||
| std::string raw_str; | ||||||||||
|
|
||||||||||
| int length = 1; | ||||||||||
|
|
||||||||||
| skip_input (); | ||||||||||
|
|
@@ -2265,15 +2267,19 @@ Lexer::parse_non_decimal_int_literal (location_t loc, IsDigitFunc is_digit_func, | |||||||||
| length++; | ||||||||||
|
|
||||||||||
| // add raw numbers | ||||||||||
| existent_str += current_char; | ||||||||||
| raw_str += current_char; | ||||||||||
| skip_input (); | ||||||||||
| current_char = peek_input (); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // convert value to decimal representation | ||||||||||
| long dec_num = std::strtol (existent_str.c_str (), nullptr, base); | ||||||||||
|
|
||||||||||
| existent_str = std::to_string (dec_num); | ||||||||||
| mpz_t dec_num; | ||||||||||
| mpz_init (dec_num); | ||||||||||
| mpz_set_str (dec_num, raw_str.c_str (), base); | ||||||||||
| char *s = mpz_get_str (NULL, 10, dec_num); | ||||||||||
| std::string dec_str = s; | ||||||||||
| free (s); | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. GMP may use a custom memory allocator, so
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This document covers general usage. Looking at the GMP usages across the GCC source, they all call |
||||||||||
| mpz_clear (dec_num); | ||||||||||
|
|
||||||||||
| // parse in type suffix if it exists | ||||||||||
| auto type_suffix_pair = parse_in_type_suffix (); | ||||||||||
|
|
@@ -2297,35 +2303,29 @@ Lexer::parse_non_decimal_int_literal (location_t loc, IsDigitFunc is_digit_func, | |||||||||
|
|
||||||||||
| loc += length - 1; | ||||||||||
|
|
||||||||||
| return Token::make_int (loc, std::move (existent_str), type_hint); | ||||||||||
| return Token::make_int (loc, std::move (dec_str), type_hint); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Parses a hex, binary or octal int literal. | ||||||||||
| TokenPtr | ||||||||||
| Lexer::parse_non_decimal_int_literals (location_t loc) | ||||||||||
| { | ||||||||||
| std::string str; | ||||||||||
| str.reserve (16); // some sensible default | ||||||||||
| str += current_char; | ||||||||||
|
|
||||||||||
| current_char = peek_input (); | ||||||||||
|
|
||||||||||
| if (current_char == 'x') | ||||||||||
| { | ||||||||||
| // hex (integer only) | ||||||||||
| return parse_non_decimal_int_literal (loc, is_x_digit, str + "x", 16); | ||||||||||
powerboat9 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
| return parse_non_decimal_int_literal (loc, is_x_digit, 16); | ||||||||||
| } | ||||||||||
| else if (current_char == 'o') | ||||||||||
| { | ||||||||||
| // octal (integer only) | ||||||||||
| return parse_non_decimal_int_literal (loc, is_octal_digit, | ||||||||||
| std::move (str), 8); | ||||||||||
| return parse_non_decimal_int_literal (loc, is_octal_digit, 8); | ||||||||||
| } | ||||||||||
| else if (current_char == 'b') | ||||||||||
| { | ||||||||||
| // binary (integer only) | ||||||||||
| return parse_non_decimal_int_literal (loc, is_bin_digit, std::move (str), | ||||||||||
| 2); | ||||||||||
| return parse_non_decimal_int_literal (loc, is_bin_digit, 2); | ||||||||||
| } | ||||||||||
| else | ||||||||||
| { | ||||||||||
|
|
||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // { dg-do run } | ||
| // { dg-require-effective-target lp64 } | ||
| // { dg-options "-O0" } | ||
| #![feature(no_core)] | ||
| #![no_core] | ||
|
|
||
| fn main() -> i32 { | ||
| let hex_val: u128 = 0x1_0000_0000_0000_0000_u128; | ||
| if (hex_val >> 64) as u8 != 1 { | ||
| return 1; | ||
| } | ||
|
|
||
| let bin_val: u128 = | ||
| 0b1_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_u128; | ||
| if (bin_val >> 64) as u8 != 1 { | ||
| return 1; | ||
| } | ||
|
|
||
| let oct_val: u128 = 0o2_000_000_000_000_000_000_000_u128; | ||
| if (oct_val >> 64) as u8 != 1 { | ||
| return 1; | ||
| } | ||
| 0 | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mpz_set_strreturn value unchecked return -1 on invalid input.Digits are already validated by
is_digit_funcassert checking this value would be dfensive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it should be fine since it's validated by is_digit_func. That said, it might still be a good idea, I'll add it.