From: "Даниил Александрович Фролов" <frolov.da@phystech.edu>
To: Marek Polacek <polacek@redhat.com>
Cc: "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>
Subject: Re: -Wformat-overflow handling for %b and %B directives in C2X standard
Date: Thu, 01 Sep 2022 14:41:17 +0500 [thread overview]
Message-ID: <1615351662024992@mail.yandex.ru> (raw)
In-Reply-To: <Yw4lD/SGLr0BN0qP@redhat.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: 0001-Support-b-B-for-Wformat-overflow-sprintf-snprintf.patch --]
[-- Type: text/x-diff; name="0001-Support-b-B-for-Wformat-overflow-sprintf-snprintf.patch", Size: 5972 bytes --]
From eb9e8241d99145020ec5c050c918c1ad3abc2701 Mon Sep 17 00:00:00 2001
From: Frolov Daniil <frolov.da@phystech.edu>
Date: Thu, 1 Sep 2022 10:55:01 +0300
Subject: [PATCH] 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.
---
gcc/gimple-ssa-sprintf.cc | 41 +++++++++++++++---------
gcc/testsuite/gcc.dg/Wformat-overflow1.c | 28 ++++++++++++++++
2 files changed, 53 insertions(+), 16 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/Wformat-overflow1.c
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);
+
+}
--
2.25.1
next prev parent reply other threads:[~2022-09-01 9:41 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-01 19:19 Frolov Daniil
2022-04-01 20:15 ` Marek Polacek
2022-04-06 21:10 ` Frolov Daniil
2022-04-11 21:56 ` Marek Polacek
2022-08-15 16:42 ` Frolov Daniil
2022-08-30 14:56 ` Marek Polacek
2022-09-01 9:41 ` Даниил Александрович Фролов [this message]
2022-11-28 17:36 ` Jeff Law
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1615351662024992@mail.yandex.ru \
--to=frolov.da@phystech.edu \
--cc=gcc-patches@gcc.gnu.org \
--cc=polacek@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).