From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2205) id 180893839C7B; Sat, 4 Jun 2022 11:18:09 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 180893839C7B 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/m2] Fix UB and literal truncation X-Act-Checkin: binutils-gdb X-Git-Author: Tom de Vries X-Git-Refname: refs/heads/master X-Git-Oldrev: 1390b65a1b93f75cdd4165f190b4a95b93add66e X-Git-Newrev: 999f7adc21cdcef5b606d2529068121dc6032b18 Message-Id: <20220604111809.180893839C7B@sourceware.org> Date: Sat, 4 Jun 2022 11:18:09 +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:18:09 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D999f7adc21cd= cef5b606d2529068121dc6032b18 commit 999f7adc21cdcef5b606d2529068121dc6032b18 Author: Tom de Vries Date: Sat Jun 4 13:17:33 2022 +0200 [gdb/m2] Fix UB and literal truncation =20 Rewrite parse_number to use ULONGEST instead of LONGEST, to fix UB erro= rs as mentioned in PR29163. =20 Furthermore, make sure we error out on overflow instead of truncating i= n all cases. =20 Tested on x86_64-linux, with a build with --enable-targets=3Dall. =20 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=3D29163 Diff: --- gdb/m2-exp.y | 47 ++++++++++++++++-------------= ---- gdb/testsuite/gdb.base/parse_number.exp | 3 +-- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/gdb/m2-exp.y b/gdb/m2-exp.y index 85bac11b8fb..d3e917bb8d7 100644 --- a/gdb/m2-exp.y +++ b/gdb/m2-exp.y @@ -582,12 +582,11 @@ static int parse_number (int olen) { const char *p =3D pstate->lexptr; - LONGEST n =3D 0; - LONGEST prevn =3D 0; + ULONGEST n =3D 0; + ULONGEST prevn =3D 0; int c,i,ischar=3D0; int base =3D input_radix; int len =3D olen; - int unsigned_p =3D number_sign =3D=3D 1 ? 1 : 0; =20 if(p[len-1] =3D=3D 'H') { @@ -639,16 +638,11 @@ parse_number (int olen) n+=3Di; if(i >=3D base) return ERROR; - if(!unsigned_p && number_sign =3D=3D 1 && (prevn >=3D n)) - unsigned_p=3D1; /* Try something unsigned */ - /* Don't do the range check if n=3D=3Di and i=3D=3D0, since that spe= cial - case will give an overflow error. */ - if(RANGE_CHECK && n!=3Di && i) - { - if((unsigned_p && (unsigned)prevn >=3D (unsigned)n) || - ((!unsigned_p && number_sign=3D=3D-1) && -prevn <=3D -n)) - range_error (_("Overflow on numeric constant.")); - } + if (n =3D=3D 0 && prevn =3D=3D 0) + ; + else if (RANGE_CHECK && prevn >=3D n) + range_error (_("Overflow on numeric constant.")); + prevn=3Dn; } =20 @@ -661,17 +655,22 @@ parse_number (int olen) yylval.ulval =3D n; return CHAR; } - else if ( unsigned_p && number_sign =3D=3D 1) - { - yylval.ulval =3D n; - return UINT; - } - else if((unsigned_p && (n<0))) { - range_error (_("Overflow on numeric constant -- number too large.")); - /* But, this can return if range_check =3D=3D range_warn. */ - } - yylval.lval =3D n; - return INT; + + int int_bits =3D gdbarch_int_bit (pstate->gdbarch ()); + bool have_signed =3D number_sign =3D=3D -1; + bool have_unsigned =3D number_sign =3D=3D 1; + if (have_signed && fits_in_type (number_sign, n, int_bits, true)) + { + yylval.lval =3D n; + return INT; + } + else if (have_unsigned && fits_in_type (number_sign, n, int_bits, false)) + { + yylval.ulval =3D n; + return UINT; + } + else + error (_("Overflow on numeric constant.")); } =20 =20 diff --git a/gdb/testsuite/gdb.base/parse_number.exp b/gdb/testsuite/gdb.ba= se/parse_number.exp index 4189ccaf92c..6e0091278a9 100644 --- a/gdb/testsuite/gdb.base/parse_number.exp +++ b/gdb/testsuite/gdb.base/parse_number.exp @@ -161,8 +161,7 @@ proc parse_number { lang n } { return [list "CARDINAL" $n] } else { # Overflow. - # Some truncated value or re_overflow, should be re_overflow. - return [list ($re_overflow|CARDINAL|INTEGER) ($re_overflow|$any)] + return [list $re_overflow $re_overflow] } } elseif { $lang =3D=3D "fortran" } { if { [fits_in_type $n $int_bits s] } {