PR middle-end/79448 - unhelpful -Wformat-truncation=2 warning
gcc/testsuite/ChangeLog: PR middle-end/79448 * gcc.dg/tree-ssa/builtin-snprintf-warn-3.c: New test. * gcc.dg/tree-ssa/pr79448-2.c: New test. * gcc.dg/tree-ssa/pr79448.c: New test. gcc/ChangeLog: PR middle-end/79448 * gimple-ssa-sprintf.c (format_directive): Avoid issuing INT_MAX warning for strings of unknown length. From-SVN: r245437
This commit is contained in:
parent
355930ab26
commit
bf00c9e080
6 changed files with 259 additions and 3 deletions
|
@ -1,3 +1,9 @@
|
|||
2017-02-14 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR middle-end/79448
|
||||
* gimple-ssa-sprintf.c (format_directive): Avoid issuing INT_MAX
|
||||
warning for strings of unknown length.
|
||||
|
||||
2017-02-13 Segher Boessenkool <segher@kernel.crashing.org>
|
||||
|
||||
* config.gcc (supported_defaults) [powerpc*-*-*]: Update.
|
||||
|
|
|
@ -2559,13 +2559,16 @@ format_directive (const pass_sprintf_length::call_info &info,
|
|||
res->range.max += fmtres.range.max;
|
||||
|
||||
/* Raise the total unlikely maximum by the larger of the maximum
|
||||
and the unlikely maximum. It doesn't matter if the unlikely
|
||||
maximum overflows. */
|
||||
and the unlikely maximum. */
|
||||
unsigned HOST_WIDE_INT save = res->range.unlikely;
|
||||
if (fmtres.range.max < fmtres.range.unlikely)
|
||||
res->range.unlikely += fmtres.range.unlikely;
|
||||
else
|
||||
res->range.unlikely += fmtres.range.max;
|
||||
|
||||
if (res->range.unlikely < save)
|
||||
res->range.unlikely = HOST_WIDE_INT_M1U;
|
||||
|
||||
res->range.min += fmtres.range.min;
|
||||
res->range.likely += fmtres.range.likely;
|
||||
|
||||
|
@ -2616,7 +2619,12 @@ format_directive (const pass_sprintf_length::call_info &info,
|
|||
|
||||
/* Has the likely and maximum directive output exceeded INT_MAX? */
|
||||
bool likelyximax = *dir.beg && res->range.likely > target_int_max ();
|
||||
bool maxximax = *dir.beg && res->range.max > target_int_max ();
|
||||
/* Don't consider the maximum to be in excess when it's the result
|
||||
of a string of unknown length (i.e., whose maximum has been set
|
||||
to be greater than or equal to HOST_WIDE_INT_MAX. */
|
||||
bool maxximax = (*dir.beg
|
||||
&& res->range.max > target_int_max ()
|
||||
&& res->range.max < HOST_WIDE_INT_MAX);
|
||||
|
||||
if (!warned
|
||||
/* Warn for the likely output size at level 1. */
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2017-02-14 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR middle-end/79448
|
||||
* gcc.dg/tree-ssa/builtin-snprintf-warn-3.c: New test.
|
||||
* gcc.dg/tree-ssa/pr79448-2.c: New test.
|
||||
* gcc.dg/tree-ssa/pr79448.c: New test.
|
||||
|
||||
2017-02-14 Jeff Law <law@redhat.com>
|
||||
|
||||
PR tree-optimization/79095
|
||||
|
|
193
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-warn-3.c
Normal file
193
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-warn-3.c
Normal file
|
@ -0,0 +1,193 @@
|
|||
/* PR middle-end/79448 - unhelpful -Wformat-truncation=2 warning
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O2 -Wformat -Wformat-truncation=2 -ftrack-macro-expansion=0" } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef __WCHAR_TYPE__ wchar_t;
|
||||
|
||||
#define INT_MAX __INT_MAX__
|
||||
#define INT_MIN (-INT_MAX - 1)
|
||||
|
||||
/* When debugging, define LINE to the line number of the test case to exercise
|
||||
and avoid exercising any of the others. The buffer and objsize macros
|
||||
below make use of LINE to avoid warnings for other lines. */
|
||||
#ifndef LINE
|
||||
# define LINE 0
|
||||
#endif
|
||||
|
||||
extern int int_value (void);
|
||||
extern size_t size_value (void);
|
||||
|
||||
int int_range (int min, int max)
|
||||
{
|
||||
int n = int_value ();
|
||||
return n < min || max < n ? min : n;
|
||||
}
|
||||
|
||||
void sink (int, char*, char*);
|
||||
|
||||
int dummy_snprintf (char*, size_t, const char*, ...);
|
||||
|
||||
char fixed_buffer [256];
|
||||
extern char *unknown_buffer;
|
||||
extern size_t unknown_size;
|
||||
|
||||
/* Helper to expand function to either __builtin_f or dummy_f to
|
||||
make debugging GCC easy. */
|
||||
#define FUNC(f) \
|
||||
((!LINE || LINE == __LINE__) ? __builtin_ ## f : dummy_ ## f)
|
||||
|
||||
/* Helper test macro. */
|
||||
#define T(size, ...) \
|
||||
do { \
|
||||
size_t n = size < 0 ? unknown_size : size; \
|
||||
char *buf = size < 0 ? unknown_buffer \
|
||||
: n < sizeof fixed_buffer \
|
||||
? fixed_buffer + sizeof fixed_buffer - size \
|
||||
: unknown_buffer; \
|
||||
FUNC (snprintf) (buf, n, __VA_ARGS__); \
|
||||
sink (0, fixed_buffer, unknown_buffer); \
|
||||
} while (0)
|
||||
|
||||
/* Return a value in the range [MIN, MAX]. */
|
||||
#define IR(min, max) int_range (min, max)
|
||||
|
||||
struct Arrays
|
||||
{
|
||||
char a1[1];
|
||||
char a4k[4096];
|
||||
char a4kp1[4097];
|
||||
#if INT_MAX < LONG_MAX
|
||||
char amax[INT_MAX];
|
||||
#else
|
||||
char amax[32767];
|
||||
#endif
|
||||
char ax[];
|
||||
};
|
||||
|
||||
void test_string_unchecked (const char *s, const struct Arrays *ar)
|
||||
{
|
||||
/* Verify there is no warning with strings of unknown length. */
|
||||
T (-1, "%-s", s);
|
||||
T (-1, "%-s", ar->ax);
|
||||
|
||||
T (-1, "%s%s", s, s);
|
||||
T (-1, "%s%s", "", s);
|
||||
T (-1, "%s%s", s, "1");
|
||||
T (-1, "%s%s", "1", s);
|
||||
|
||||
/* Verify there is no warning with strings of length that cannot
|
||||
exceed 4k (because of the array size). */
|
||||
T (-1, "%-s", ar->a1);
|
||||
T (-1, "%-s", ar->a4k);
|
||||
|
||||
/* Verify there's no "exceeds minimum required size of 4095" warning
|
||||
with multiple %s directives and a combination of strings of unknown
|
||||
(and potentially unbounded) length and strings whose length is
|
||||
bounded by the size of the arrays they are stored in. */
|
||||
T (-1, "%s%s", s, ar->a4k);
|
||||
T (-1, "%s%s", ar->a4k, s);
|
||||
T (-1, "%s%s", ar->a4k, ar->a4k);
|
||||
T (-1, "%s%s", ar->a4k, "123");
|
||||
T (-1, "%s%s", "123", ar->a4k);
|
||||
T (-1, "%s%s", ar->ax, ar->a4k);
|
||||
T (-1, "%s%s", ar->a4k, ar->ax);
|
||||
|
||||
/* Verify that an array that fits a string longer than 4095 bytes
|
||||
does trigger a warning. */
|
||||
T (-1, "%-s", ar->a4kp1); /* { dg-warning "directive output between 0 and 4096 bytes may exceed minimum required size of 4095" } */
|
||||
|
||||
/* Also verify that a %s directive with width greater than 4095
|
||||
triggers a warning even if the argument is not longer than 4k. */
|
||||
T (-1, "%*s", 4096, ar->a4k); /* { dg-warning "directive output of 4096 bytes exceeds minimum required size of 4095" } */
|
||||
|
||||
/* Verify that precision constrains the putput and suppresses the 4k
|
||||
warning. */
|
||||
T (-1, "%.*s", 4095, ar->a4kp1);
|
||||
|
||||
T (-1, "%s %s", s, "");
|
||||
T (-1, "%s %s", "", s);
|
||||
T (-1, "%s %s", s, "1");
|
||||
T (-1, "%s %s", "1", s);
|
||||
|
||||
T (-1, "%s%s%s", s, "1", s);
|
||||
T (-1, "%s%s%s", "1", s, "1");
|
||||
T (-1, "%s%s%s", s, s, s);
|
||||
T (-1, "%*s%*s%*s", 4093, s, 4094, s, 4095, s);
|
||||
T (-1, "%s %s %s", s, s, s);
|
||||
T (-1, "%s %s %s", ar->a4k, ar->a4k, ar->a4k);
|
||||
T (-1, "%s %s %s", ar->ax, ar->ax, ar->ax);
|
||||
|
||||
/* Verify that an array of INT_MAX elements doesn't trigger the INT_MAX
|
||||
warning (LP64 only). */
|
||||
T (-1, "%-s", ar->amax); /* { dg-warning "directive output between 0 and \[0-9\]+ bytes may exceed minimum required size of 4095" } */
|
||||
}
|
||||
|
||||
#undef T
|
||||
/* Helper test macro. */
|
||||
#define T(size, ...) \
|
||||
do { \
|
||||
size_t n = size < 0 ? unknown_size : size; \
|
||||
char *buf = size < 0 ? unknown_buffer \
|
||||
: n < sizeof fixed_buffer \
|
||||
? fixed_buffer + sizeof fixed_buffer - size \
|
||||
: unknown_buffer; \
|
||||
int r = FUNC (snprintf) (buf, n, __VA_ARGS__); \
|
||||
sink (r, fixed_buffer, unknown_buffer); \
|
||||
} while (0)
|
||||
|
||||
void test_string_checked (const char *s, const struct Arrays *ar)
|
||||
{
|
||||
/* Verify there is no warning with strings of unknown length. */
|
||||
T (-1, "%-s", s);
|
||||
T (-1, "%-s", ar->ax);
|
||||
|
||||
T (-1, "%s%s", s, s);
|
||||
T (-1, "%s%s", "", s);
|
||||
T (-1, "%s%s", s, "1");
|
||||
T (-1, "%s%s", "1", s);
|
||||
|
||||
/* Verify there is no warning with strings of length that cannot
|
||||
exceed 4k (because of the array size). */
|
||||
T (-1, "%-s", ar->a1);
|
||||
T (-1, "%-s", ar->a4k);
|
||||
|
||||
/* Verify there's no "exceeds minimum required size of 4095" warning
|
||||
with multiple %s directives and a combination of strings of unknown
|
||||
(and potentially unbounded) length and strings whose length is
|
||||
bounded by the size of the arrays they are stored in. */
|
||||
T (-1, "%s%s", s, ar->a4k);
|
||||
T (-1, "%s%s", ar->a4k, s);
|
||||
T (-1, "%s%s", ar->a4k, ar->a4k);
|
||||
T (-1, "%s%s", ar->a4k, "123");
|
||||
T (-1, "%s%s", "123", ar->a4k);
|
||||
T (-1, "%s%s", ar->ax, ar->a4k);
|
||||
T (-1, "%s%s", ar->a4k, ar->ax);
|
||||
|
||||
/* Verify that an array that fits a string longer than 4095 bytes
|
||||
does trigger a warning. */
|
||||
T (-1, "%-s", ar->a4kp1); /* { dg-warning "directive output between 0 and 4096 bytes may exceed minimum required size of 4095" } */
|
||||
|
||||
/* Also verify that a %s directive with width greater than 4095
|
||||
triggers a warning even if the argument is not longer than 4k. */
|
||||
T (-1, "%*s", 4096, ar->a4k); /* { dg-warning "directive output of 4096 bytes exceeds minimum required size of 4095" } */
|
||||
|
||||
/* Verify that precision constrains the putput and suppresses the 4k
|
||||
warning. */
|
||||
T (-1, "%.*s", 4095, ar->a4kp1);
|
||||
|
||||
T (-1, "%s %s", s, "");
|
||||
T (-1, "%s %s", "", s);
|
||||
T (-1, "%s %s", s, "1");
|
||||
T (-1, "%s %s", "1", s);
|
||||
|
||||
T (-1, "%s%s%s", s, "1", s);
|
||||
T (-1, "%s%s%s", "1", s, "1");
|
||||
T (-1, "%s%s%s", s, s, s);
|
||||
T (-1, "%*s%*s%*s", 4093, s, 4094, s, 4095, s);
|
||||
T (-1, "%s %s %s", s, s, s);
|
||||
T (-1, "%s %s %s", ar->a4k, ar->a4k, ar->a4k);
|
||||
T (-1, "%s %s %s", ar->ax, ar->ax, ar->ax);
|
||||
|
||||
T (-1, "%-s", ar->amax); /* { dg-warning "directive output between 0 and \[0-9\]+ bytes may exceed minimum required size of 4095" } */
|
||||
}
|
21
gcc/testsuite/gcc.dg/tree-ssa/pr79448-2.c
Normal file
21
gcc/testsuite/gcc.dg/tree-ssa/pr79448-2.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
/* PR middle-end/79448 - unhelpful -Wformat-truncation=2 warning
|
||||
Verify that there's no warning with optimization.
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O2 -Wall -Wformat -Wformat-truncation=2" } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
extern int
|
||||
snprintf (char*, size_t, const char*, ...);
|
||||
|
||||
char*
|
||||
gettext (char*);
|
||||
|
||||
char*
|
||||
fill (char *buf, size_t len, int count)
|
||||
{
|
||||
if (snprintf (buf, len, "%s: %d", gettext ("count"), count) >= len) /* { dg-bogus "directive output of 2 bytes causes result to exceed .INT_MAX." */
|
||||
return 0;
|
||||
|
||||
return buf;
|
||||
}
|
21
gcc/testsuite/gcc.dg/tree-ssa/pr79448.c
Normal file
21
gcc/testsuite/gcc.dg/tree-ssa/pr79448.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
/* PR middle-end/79448 - unhelpful -Wformat-truncation=2 warning
|
||||
Verify that there's no warning without optimization.
|
||||
{ dg-do compile }
|
||||
{ dg-options "-Wall -Wformat -Wformat-truncation=2" } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
extern int
|
||||
snprintf (char*, size_t, const char*, ...);
|
||||
|
||||
char*
|
||||
gettext (char*);
|
||||
|
||||
char*
|
||||
fill (char *buf, size_t len, int count)
|
||||
{
|
||||
if (snprintf (buf, len, "%s: %d", gettext ("count"), count) >= len) /* { dg-bogus "directive output of 2 bytes causes result to exceed .INT_MAX." */
|
||||
return 0;
|
||||
|
||||
return buf;
|
||||
}
|
Loading…
Add table
Reference in a new issue