From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2205) id D84CD383801E; Sat, 4 Jun 2022 11:17:53 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D84CD383801E Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Tom de Vries To: gdb-cvs@sourceware.org Subject: [binutils-gdb] [gdb/go] Fix literal truncation X-Act-Checkin: binutils-gdb X-Git-Author: Tom de Vries X-Git-Refname: refs/heads/master X-Git-Oldrev: a2c0d041fdbf9d661099e31629c96cdd666e8b83 X-Git-Newrev: 4c4d769ab7b01dab8ff8c66209f992de98095a00 Message-Id: <20220604111753.D84CD383801E@sourceware.org> Date: Sat, 4 Jun 2022 11:17:53 +0000 (GMT) X-BeenThere: gdb-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Jun 2022 11:17:53 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D4c4d769ab7b0= 1dab8ff8c66209f992de98095a00 commit 4c4d769ab7b01dab8ff8c66209f992de98095a00 Author: Tom de Vries Date: Sat Jun 4 13:17:33 2022 +0200 [gdb/go] Fix literal truncation =20 Make sure we error out on overflow instead of truncating in all cases. =20 The current implementation of parse_number contains a comment about PR1= 6377, but that's related to C-like languages. In absence of information of w= hether the same fix is needed for go, take the conservative approach and keep behaviour for decimals unchanged. =20 Tested on x86_64-linux, with a build with --enable-targets=3Dall. Diff: --- gdb/go-exp.y | 95 ++++++++++-------------------= ---- gdb/testsuite/gdb.base/parse_number.exp | 2 +- 2 files changed, 30 insertions(+), 67 deletions(-) diff --git a/gdb/go-exp.y b/gdb/go-exp.y index 1b9b6ea7e90..f786ec20171 100644 --- a/gdb/go-exp.y +++ b/gdb/go-exp.y @@ -649,7 +649,6 @@ parse_number (struct parser_state *par_state, { ULONGEST n =3D 0; ULONGEST prevn =3D 0; - ULONGEST un; =20 int i =3D 0; int c; @@ -662,10 +661,6 @@ parse_number (struct parser_state *par_state, /* We have found a "L" or "U" suffix. */ int found_suffix =3D 0; =20 - ULONGEST high_bit; - struct type *signed_type; - struct type *unsigned_type; - if (parsed_float) { const struct builtin_go_type *builtin_go_types @@ -777,18 +772,12 @@ parse_number (struct parser_state *par_state, if (i >=3D base) return ERROR; /* Invalid digit in this base. */ =20 - /* Portably test for overflow (only works for nonzero values, so make - a second check for zero). FIXME: Can't we just make n and prevn - unsigned and avoid this? */ - if (c !=3D 'l' && c !=3D 'u' && (prevn >=3D n) && n !=3D 0) - unsigned_p =3D 1; /* Try something unsigned. */ - - /* Portably test for unsigned overflow. - FIXME: This check is wrong; for example it doesn't find overflow - on 0x123456789 when LONGEST is 32 bits. */ - if (c !=3D 'l' && c !=3D 'u' && n !=3D 0) + if (c !=3D 'l' && c !=3D 'u') { - if ((unsigned_p && prevn >=3D n)) + /* Test for overflow. */ + if (n =3D=3D 0 && prevn =3D=3D 0) + ; + else if (prevn >=3D n) error (_("Numeric constant too large.")); } prevn =3D n; @@ -806,57 +795,31 @@ parse_number (struct parser_state *par_state, the case where it is we just always shift the value more than once, with fewer bits each time. */ =20 - un =3D n >> 2; - if (long_p =3D=3D 0 - && (un >> (gdbarch_int_bit (par_state->gdbarch ()) - 2)) =3D=3D 0) - { - high_bit - =3D ((ULONGEST)1) << (gdbarch_int_bit (par_state->gdbarch ()) - 1); - - /* A large decimal (not hex or octal) constant (between INT_MAX - and UINT_MAX) is a long or unsigned long, according to ANSI, - never an unsigned int, but this code treats it as unsigned - int. This probably should be fixed. GCC gives a warning on - such constants. */ - - unsigned_type =3D parse_type (par_state)->builtin_unsigned_int; - signed_type =3D parse_type (par_state)->builtin_int; - } - else if (long_p <=3D 1 - && (un >> (gdbarch_long_bit (par_state->gdbarch ()) - 2)) =3D=3D 0) - { - high_bit - =3D ((ULONGEST)1) << (gdbarch_long_bit (par_state->gdbarch ()) - 1); - unsigned_type =3D parse_type (par_state)->builtin_unsigned_long; - signed_type =3D parse_type (par_state)->builtin_long; - } + int int_bits =3D gdbarch_int_bit (par_state->gdbarch ()); + int long_bits =3D gdbarch_long_bit (par_state->gdbarch ()); + int long_long_bits =3D gdbarch_long_long_bit (par_state->gdbarch ()); + bool have_signed =3D !unsigned_p; + bool have_int =3D long_p =3D=3D 0; + bool have_long =3D long_p <=3D 1; + if (have_int && have_signed && fits_in_type (1, n, int_bits, true)) + putithere->typed_val_int.type =3D parse_type (par_state)->builtin_int; + else if (have_int && fits_in_type (1, n, int_bits, false)) + putithere->typed_val_int.type + =3D parse_type (par_state)->builtin_unsigned_int; + else if (have_long && have_signed && fits_in_type (1, n, long_bits, true= )) + putithere->typed_val_int.type =3D parse_type (par_state)->builtin_long; + else if (have_long && fits_in_type (1, n, long_bits, false)) + putithere->typed_val_int.type + =3D parse_type (par_state)->builtin_unsigned_long; + else if (have_signed && fits_in_type (1, n, long_long_bits, true)) + putithere->typed_val_int.type + =3D parse_type (par_state)->builtin_long_long; + else if (fits_in_type (1, n, long_long_bits, false)) + putithere->typed_val_int.type + =3D parse_type (par_state)->builtin_unsigned_long_long; else - { - int shift; - if (sizeof (ULONGEST) * HOST_CHAR_BIT - < gdbarch_long_long_bit (par_state->gdbarch ())) - /* A long long does not fit in a LONGEST. */ - shift =3D (sizeof (ULONGEST) * HOST_CHAR_BIT - 1); - else - shift =3D (gdbarch_long_long_bit (par_state->gdbarch ()) - 1); - high_bit =3D (ULONGEST) 1 << shift; - unsigned_type =3D parse_type (par_state)->builtin_unsigned_long_long; - signed_type =3D parse_type (par_state)->builtin_long_long; - } - - putithere->typed_val_int.val =3D n; - - /* If the high bit of the worked out type is set then this number - has to be unsigned. */ - - if (unsigned_p || (n & high_bit)) - { - putithere->typed_val_int.type =3D unsigned_type; - } - else - { - putithere->typed_val_int.type =3D signed_type; - } + error (_("Numeric constant too large.")); + putithere->typed_val_int.val =3D n; =20 return INT; } diff --git a/gdb/testsuite/gdb.base/parse_number.exp b/gdb/testsuite/gdb.ba= se/parse_number.exp index 87554ccf995..bedb4d64c5a 100644 --- a/gdb/testsuite/gdb.base/parse_number.exp +++ b/gdb/testsuite/gdb.base/parse_number.exp @@ -214,7 +214,7 @@ proc parse_number { lang n } { return [list "unsigned long long" $n] } else { # Overflow. - if { [c_like $lang] } { + if { [c_like $lang] || $lang =3D=3D "go" } { return [list $re_overflow $re_overflow] } else { # Some truncated value or re_overflow, should be re_overflow.