From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) by sourceware.org (Postfix) with ESMTPS id C4F58383E6B9 for ; Mon, 23 May 2022 11:05:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org C4F58383E6B9 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 0192F218CE for ; Mon, 23 May 2022 11:05:19 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id DE784139F5 for ; Mon, 23 May 2022 11:05:18 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id AAcjNW5qi2JxFQAAMHmgww (envelope-from ) for ; Mon, 23 May 2022 11:05:18 +0000 From: Tom de Vries To: gdb-patches@sourceware.org Subject: [PATCH 4/8] [gdb/go] Fix literal truncation Date: Mon, 23 May 2022 13:05:14 +0200 Message-Id: <20220523110518.2447-4-tdevries@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220523110518.2447-1-tdevries@suse.de> References: <20220523110518.2447-1-tdevries@suse.de> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-12.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 23 May 2022 11:05:21 -0000 Make sure we error out on overflow instead of truncating in all cases. The current implementation of parse_number contains a comment about PR16377, but that's related to C-like languages. In absence of information of whether the same fix is needed for go, take the conservative approach and keep behaviour for decimals unchanged. Tested on x86_64-linux, with a build with --enable-targets=all. --- 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 = 0; ULONGEST prevn = 0; - ULONGEST un; int i = 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 = 0; - 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 >= base) return ERROR; /* Invalid digit in this base. */ - /* 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 != 'l' && c != 'u' && (prevn >= n) && n != 0) - unsigned_p = 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 != 'l' && c != 'u' && n != 0) + if (c != 'l' && c != 'u') { - if ((unsigned_p && prevn >= n)) + /* Test for overflow. */ + if (n == 0 && prevn == 0) + ; + else if (prevn >= n) error (_("Numeric constant too large.")); } prevn = 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. */ - un = n >> 2; - if (long_p == 0 - && (un >> (gdbarch_int_bit (par_state->gdbarch ()) - 2)) == 0) - { - high_bit - = ((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 = parse_type (par_state)->builtin_unsigned_int; - signed_type = parse_type (par_state)->builtin_int; - } - else if (long_p <= 1 - && (un >> (gdbarch_long_bit (par_state->gdbarch ()) - 2)) == 0) - { - high_bit - = ((ULONGEST)1) << (gdbarch_long_bit (par_state->gdbarch ()) - 1); - unsigned_type = parse_type (par_state)->builtin_unsigned_long; - signed_type = parse_type (par_state)->builtin_long; - } + int int_bits = gdbarch_int_bit (par_state->gdbarch ()); + int long_bits = gdbarch_long_bit (par_state->gdbarch ()); + int long_long_bits = gdbarch_long_long_bit (par_state->gdbarch ()); + bool have_signed = !unsigned_p; + bool have_int = long_p == 0; + bool have_long = long_p <= 1; + if (have_int && have_signed && fits_in_type (1, n, int_bits, true)) + putithere->typed_val_int.type = parse_type (par_state)->builtin_int; + else if (have_int && fits_in_type (1, n, int_bits, false)) + putithere->typed_val_int.type + = 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 = parse_type (par_state)->builtin_long; + else if (have_long && fits_in_type (1, n, long_bits, false)) + putithere->typed_val_int.type + = 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 + = parse_type (par_state)->builtin_long_long; + else if (fits_in_type (1, n, long_long_bits, false)) + putithere->typed_val_int.type + = 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 = (sizeof (ULONGEST) * HOST_CHAR_BIT - 1); - else - shift = (gdbarch_long_long_bit (par_state->gdbarch ()) - 1); - high_bit = (ULONGEST) 1 << shift; - unsigned_type = parse_type (par_state)->builtin_unsigned_long_long; - signed_type = parse_type (par_state)->builtin_long_long; - } - - putithere->typed_val_int.val = 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 = unsigned_type; - } - else - { - putithere->typed_val_int.type = signed_type; - } + error (_("Numeric constant too large.")); + putithere->typed_val_int.val = n; return INT; } diff --git a/gdb/testsuite/gdb.base/parse_number.exp b/gdb/testsuite/gdb.base/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 == "go" } { return [list $re_overflow $re_overflow] } else { # Some truncated value or re_overflow, should be re_overflow. -- 2.35.3