From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2119) id 61EB83858C62; Mon, 28 Nov 2022 17:35:49 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 61EB83858C62 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1669656949; bh=CTO0n9aDz8B+y596Dun5c1RYdcUOYn6k5I3t7jlR1zI=; h=From:To:Subject:Date:From; b=SjYiy4MAHeDy93Jv7zNPJvnm8EfI+1TWEKtT7BMb5DtEkwXvyKpOszAoKXFzbPBnc VtbySGm4ORo/dh9rT+AML8rHTn10eWROaHpuu6C2lWJEkoFR4JZ8ptc0l9KhchQ+BK ccIHOuFYVzBXwyEu29hFVkM4ha8OSlBK4sE3M/BU= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jeff Law To: gcc-cvs@gcc.gnu.org Subject: [gcc r13-4372] Support %b, %B for -Wformat-overflow (sprintf, snprintf) X-Act-Checkin: gcc X-Git-Author: Frolov Daniil X-Git-Refname: refs/heads/master X-Git-Oldrev: 75e562d2c4303d3918be9d1563284b0c580c5e45 X-Git-Newrev: aa353bd9a03b0d5ba92efe082b625d6c5ed6a79d Message-Id: <20221128173549.61EB83858C62@sourceware.org> Date: Mon, 28 Nov 2022 17:35:49 +0000 (GMT) List-Id: https://gcc.gnu.org/g:aa353bd9a03b0d5ba92efe082b625d6c5ed6a79d commit r13-4372-gaa353bd9a03b0d5ba92efe082b625d6c5ed6a79d Author: Frolov Daniil Date: Mon Nov 28 12:35:13 2022 -0500 Support %b, %B for -Wformat-overflow (sprintf, snprintf) gcc/ChangeLog: * gimple-ssa-sprintf.cc (fmtresult::type_max_digits): Handle base == 2. (tree_digits): Likewise. (format_integer): Likewise. (parse_directive): Add cases for %b and %B directives. gcc/testsuite/ChangeLog: * gcc.dg/Wformat-overflow1.c: New test. Diff: --- gcc/gimple-ssa-sprintf.cc | 41 +++++++++++++++++++------------- gcc/testsuite/gcc.dg/Wformat-overflow1.c | 28 ++++++++++++++++++++++ 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/gcc/gimple-ssa-sprintf.cc b/gcc/gimple-ssa-sprintf.cc index a888b5ac7d5..1dd9b0dc46b 100644 --- a/gcc/gimple-ssa-sprintf.cc +++ b/gcc/gimple-ssa-sprintf.cc @@ -535,6 +535,8 @@ fmtresult::type_max_digits (tree type, int base) unsigned prec = TYPE_PRECISION (type); switch (base) { + case 2: + return prec; case 8: return (prec + 2) / 3; case 10: @@ -804,9 +806,9 @@ ilog (unsigned HOST_WIDE_INT x, int base) /* Return the number of bytes resulting from converting into a string the INTEGER_CST tree node X in BASE with a minimum of PREC digits. PLUS indicates whether 1 for a plus sign should be added for positive - numbers, and PREFIX whether the length of an octal ('O') or hexadecimal - ('0x') prefix should be added for nonzero numbers. Return -1 if X cannot - be represented. */ + numbers, and PREFIX whether the length of an octal ('0') or hexadecimal + ('0x') or binary ('0b') prefix should be added for nonzero numbers. + Return -1 if X cannot be represented. */ static HOST_WIDE_INT tree_digits (tree x, int base, HOST_WIDE_INT prec, bool plus, bool prefix) @@ -857,11 +859,11 @@ tree_digits (tree x, int base, HOST_WIDE_INT prec, bool plus, bool prefix) /* Adjust a non-zero value for the base prefix, either hexadecimal, or, unless precision has resulted in a leading zero, also octal. */ - if (prefix && absval && (base == 16 || prec <= ndigs)) + if (prefix && absval) { - if (base == 8) + if (base == 8 && prec <= ndigs) res += 1; - else if (base == 16) + else if (base == 16 || base == 2) /* 0x...(0X...) or 0b...(0B...). */ res += 2; } @@ -1209,7 +1211,7 @@ format_integer (const directive &dir, tree arg, pointer_query &ptr_qry) /* True when a conversion is preceded by a prefix indicating the base of the argument (octal or hexadecimal). */ - bool maybebase = dir.get_flag ('#'); + const bool maybebase = dir.get_flag ('#'); /* True when a signed conversion is preceded by a sign or space. */ bool maybesign = false; @@ -1229,6 +1231,10 @@ format_integer (const directive &dir, tree arg, pointer_query &ptr_qry) case 'u': base = 10; break; + case 'b': + case 'B': + base = 2; + break; case 'o': base = 8; break; @@ -1240,6 +1246,8 @@ format_integer (const directive &dir, tree arg, pointer_query &ptr_qry) gcc_unreachable (); } + const unsigned adj = (sign | maybebase) + (base == 2 || base == 16); + /* The type of the "formal" argument expected by the directive. */ tree dirtype = NULL_TREE; @@ -1350,11 +1358,9 @@ format_integer (const directive &dir, tree arg, pointer_query &ptr_qry) res.range.unlikely = res.range.max; /* Bump up the counters if WIDTH is greater than LEN. */ - res.adjust_for_width_or_precision (dir.width, dirtype, base, - (sign | maybebase) + (base == 16)); + res.adjust_for_width_or_precision (dir.width, dirtype, base, adj); /* Bump up the counters again if PRECision is greater still. */ - res.adjust_for_width_or_precision (dir.prec, dirtype, base, - (sign | maybebase) + (base == 16)); + res.adjust_for_width_or_precision (dir.prec, dirtype, base, adj); return res; } @@ -1503,17 +1509,15 @@ format_integer (const directive &dir, tree arg, pointer_query &ptr_qry) if (res.range.min == 1) res.range.likely += base == 8 ? 1 : 2; else if (res.range.min == 2 - && base == 16 + && (base == 16 || base == 2) && (dir.width[0] == 2 || dir.prec[0] == 2)) ++res.range.likely; } } res.range.unlikely = res.range.max; - res.adjust_for_width_or_precision (dir.width, dirtype, base, - (sign | maybebase) + (base == 16)); - res.adjust_for_width_or_precision (dir.prec, dirtype, base, - (sign | maybebase) + (base == 16)); + res.adjust_for_width_or_precision (dir.width, dirtype, base, adj); + res.adjust_for_width_or_precision (dir.prec, dirtype, base, adj); return res; } @@ -3725,6 +3729,11 @@ parse_directive (call_info &info, dir.fmtfunc = format_integer; break; + case 'b': + case 'B': + dir.fmtfunc = format_integer; + break; + case 'p': /* The %p output is implementation-defined. It's possible to determine this format but due to extensions (especially diff --git a/gcc/testsuite/gcc.dg/Wformat-overflow1.c b/gcc/testsuite/gcc.dg/Wformat-overflow1.c new file mode 100644 index 00000000000..cf9766fae14 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wformat-overflow1.c @@ -0,0 +1,28 @@ +/* + { dg-do compile } + { dg-options "-Wformat-overflow -std=c2x" } +*/ + +extern int sprintf (char* restrict, const char* restrict, ...); + +void test_warn () { + + int n = __INT_MAX__; + char dst [5] = {0}; + sprintf (dst, "%b", n); /* { dg-warning "-Wformat-overflow" } */ + + sprintf (dst, "%#b", n); /* { dg-warning "-Wformat-overflow" } */ + +} + +void test_no_warn () { + + char dst [5] = {0}; + int n = 8; + sprintf (dst, "%b", n); + + char another_dst [34] = {0}; + n = __INT_MAX__; + sprintf (another_dst, "%#b", n); + +}