PR middle-end/79275 - -Wformat-overflow false positive exceeding INT_MAX in glibc sysdeps/posix/tempname.c
gcc/testsuite/ChangeLog: PR middle-end/79275 * gcc.dg/tree-ssa/builtin-sprintf-warn-11.c: New test. * gcc.dg/tree-ssa/pr79275.c: New test. gcc/ChangeLog: PR middle-end/79275 * gimple-ssa-sprintf.c (get_string_length): Set lower bound to zero. (format_string): Tighten up the range of output for non-constant strings and correct the expected range for wide non-constant strings. From-SVN: r245142
This commit is contained in:
parent
92d8bb06dc
commit
ebee1eb978
5 changed files with 419 additions and 22 deletions
|
@ -1,3 +1,10 @@
|
|||
2017-02-02 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR middle-end/79275
|
||||
* gimple-ssa-sprintf.c (get_string_length): Set lower bound to zero.
|
||||
(format_string): Tighten up the range of output for non-constant
|
||||
strings and correct the expected range for wide non-constant strings.
|
||||
|
||||
2017-02-02 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
* doc/invoke.texi (-maccumulate-args): Fix bad grammar.
|
||||
|
|
|
@ -1832,10 +1832,11 @@ get_string_length (tree str)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* When the upper bound is unknown (as assumed to be excessive)
|
||||
/* When the upper bound is unknown (it can be zero or excessive)
|
||||
set the likely length to the greater of 1 and the length of
|
||||
the shortest string. */
|
||||
the shortest string and reset the lower bound to zero. */
|
||||
res.range.likely = res.range.min ? res.range.min : warn_level > 1;
|
||||
res.range.min = 0;
|
||||
}
|
||||
|
||||
res.range.unlikely = res.range.max;
|
||||
|
@ -1986,43 +1987,89 @@ format_string (const directive &dir, tree arg)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* For a '%s' and '%ls' directive with a non-constant string,
|
||||
the minimum number of characters is the greater of WIDTH
|
||||
and either 0 in mode 1 or the smaller of PRECISION and 1
|
||||
in mode 2, and the maximum is PRECISION or -1 to disable
|
||||
tracking. */
|
||||
/* For a '%s' and '%ls' directive with a non-constant string (either
|
||||
one of a number of strings of known length or an unknown string)
|
||||
the minimum number of characters is lesser of PRECISION[0] and
|
||||
the length of the shortest known string or zero, and the maximum
|
||||
is the lessser of the length of the longest known string or
|
||||
PTRDIFF_MAX and PRECISION[1]. The likely length is either
|
||||
the minimum at level 1 and the greater of the minimum and 1
|
||||
at level 2. This result is adjust upward for width (if it's
|
||||
specified). */
|
||||
|
||||
if (dir.modifier == FMT_LEN_l)
|
||||
{
|
||||
/* A wide character converts to as few as zero bytes. */
|
||||
slen.range.min = 0;
|
||||
if (slen.range.max < target_int_max ())
|
||||
slen.range.max *= target_mb_len_max ();
|
||||
|
||||
if (slen.range.likely < target_int_max ())
|
||||
slen.range.likely *= 2;
|
||||
|
||||
if (slen.range.likely < target_int_max ())
|
||||
slen.range.unlikely *= target_mb_len_max ();
|
||||
}
|
||||
|
||||
res.range = slen.range;
|
||||
|
||||
if (dir.prec[0] >= 0)
|
||||
{
|
||||
/* Adjust the minimum to zero if the string length is unknown,
|
||||
or at most the lower bound of the precision otherwise. */
|
||||
if (slen.range.min >= target_int_max ())
|
||||
slen.range.min = 0;
|
||||
res.range.min = 0;
|
||||
else if ((unsigned HOST_WIDE_INT)dir.prec[0] < slen.range.min)
|
||||
{
|
||||
slen.range.min = dir.prec[0];
|
||||
slen.range.likely = slen.range.min;
|
||||
}
|
||||
res.range.min = dir.prec[0];
|
||||
|
||||
/* Make both maxima no greater than the upper bound of precision. */
|
||||
if ((unsigned HOST_WIDE_INT)dir.prec[1] < slen.range.max
|
||||
|| slen.range.max >= target_int_max ())
|
||||
{
|
||||
slen.range.max = dir.prec[1];
|
||||
slen.range.likely = slen.range.max;
|
||||
res.range.max = dir.prec[1];
|
||||
res.range.unlikely = dir.prec[1];
|
||||
}
|
||||
|
||||
/* If precision is constant, set the likely counter to the lesser
|
||||
of it and the maximum string length. Otherwise, if the lower
|
||||
bound of precision is greater than zero, set the likely counter
|
||||
to the minimum. Otherwise set it to zero or one based on
|
||||
the warning level. */
|
||||
if (dir.prec[0] == dir.prec[1])
|
||||
res.range.likely
|
||||
= ((unsigned HOST_WIDE_INT)dir.prec[0] < slen.range.max
|
||||
? dir.prec[0] : slen.range.max);
|
||||
else if (dir.prec[0] > 0)
|
||||
res.range.likely = res.range.min;
|
||||
else
|
||||
res.range.likely = warn_level > 1;
|
||||
}
|
||||
else if (dir.prec[1] >= 0)
|
||||
{
|
||||
res.range.min = 0;
|
||||
if ((unsigned HOST_WIDE_INT)dir.prec[1] < slen.range.max)
|
||||
res.range.max = dir.prec[1];
|
||||
res.range.likely = dir.prec[1] ? warn_level > 1 : 0;
|
||||
}
|
||||
else if (slen.range.min >= target_int_max ())
|
||||
{
|
||||
slen.range.min = 0;
|
||||
slen.range.max = HOST_WIDE_INT_MAX;
|
||||
/* At level one strings of unknown length are assumed to be
|
||||
res.range.min = 0;
|
||||
res.range.max = HOST_WIDE_INT_MAX;
|
||||
/* At level 1 strings of unknown length are assumed to be
|
||||
empty, while at level 1 they are assumed to be one byte
|
||||
long. */
|
||||
slen.range.likely = warn_level > 1;
|
||||
res.range.likely = warn_level > 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A string of unknown length unconstrained by precision is
|
||||
assumed to be empty at level 1 and just one character long
|
||||
at higher levels. */
|
||||
if (res.range.likely >= target_int_max ())
|
||||
res.range.likely = warn_level > 1;
|
||||
}
|
||||
|
||||
slen.range.unlikely = slen.range.max;
|
||||
|
||||
res.range = slen.range;
|
||||
res.knownrange = slen.knownrange;
|
||||
res.range.unlikely = res.range.max;
|
||||
}
|
||||
|
||||
/* Bump up the byte counters if WIDTH is greater. */
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2017-02-02 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR middle-end/79275
|
||||
* gcc.dg/tree-ssa/builtin-sprintf-warn-11.c: New test.
|
||||
* gcc.dg/tree-ssa/pr79275.c: New test.
|
||||
|
||||
2017-02-02 Aaron Sawdey <acsawdey@linux.vnet.ibm.com>
|
||||
|
||||
* gcc.dg/sms-8.c: Update options for powerpc*-*-*.
|
||||
|
|
323
gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-11.c
Normal file
323
gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-11.c
Normal file
|
@ -0,0 +1,323 @@
|
|||
/* PR middle-end/79275 - -Wformat-overflow false positive exceeding INT_MAX
|
||||
in glibc sysdeps/posix/tempname.c
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O2 -Wall -Wformat-overflow=1 -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;
|
||||
}
|
||||
|
||||
size_t size_range (size_t min, size_t max)
|
||||
{
|
||||
size_t n = size_value ();
|
||||
return n < min || max < n ? min : n;
|
||||
}
|
||||
|
||||
void sink (char*, char*);
|
||||
|
||||
int dummy_sprintf (char*, const char*, ...);
|
||||
|
||||
char buffer [256];
|
||||
extern char *ptr;
|
||||
|
||||
const char s0[] = "";
|
||||
const char s1[] = "1";
|
||||
const char s2[] = "12";
|
||||
const char s3[] = "123";
|
||||
const char s4[] = "1234";
|
||||
const char s5[] = "12345";
|
||||
const char s6[] = "123456";
|
||||
const char s7[] = "1234567";
|
||||
const char s8[] = "12345678";
|
||||
const char s9[] = "123456789";
|
||||
extern const char sx[];
|
||||
extern const char sy[];
|
||||
|
||||
/* Wide string literals outside the ASCII range to avoid assumptions
|
||||
about the number of narrow characters they might convert to beyond
|
||||
up to 6 bytes each (the maximum for UTF-8 not exceeded by any known
|
||||
encoding). */
|
||||
const wchar_t ws0[] = L"";
|
||||
const wchar_t ws1[] = L"\u1111";
|
||||
const wchar_t ws2[] = L"\u1111\u2222";
|
||||
const wchar_t ws3[] = L"\u1111\u2222\u3333";
|
||||
const wchar_t ws4[] = L"\u1111\u2222\u3333\u4444";
|
||||
const wchar_t ws5[] = L"\u1111\u2222\u3333\u4444\u5555";
|
||||
const wchar_t ws6[] = L"\u1111\u2222\u3333\u4444\u5555\u6666";
|
||||
const wchar_t ws7[] = L"\u1111\u2222\u3333\u4444\u5555\u6666\u7777";
|
||||
const wchar_t ws8[] =
|
||||
L"\u1111\u2222\u3333\u4444\u5555\u6666\u7777\u8888";
|
||||
const wchar_t ws9[] =
|
||||
L"\u1111\u2222\u3333\u4444\u5555\u6666\u7777\u8888\u9999";
|
||||
extern const wchar_t wsx[];
|
||||
extern const wchar_t wsy[];
|
||||
|
||||
static const int imin = INT_MIN;
|
||||
static const int imax = INT_MAX;
|
||||
|
||||
/* Evaluate to an array of SIZE characters when non-negative, or to
|
||||
a pointer to an unknown object otherwise. */
|
||||
#define buffer(size) \
|
||||
((0 <= size) ? buffer + sizeof buffer - (size) : ptr)
|
||||
|
||||
/* 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)
|
||||
|
||||
/* Macro to verify that calls to __builtin_sprintf (i.e., with no size
|
||||
argument) issue diagnostics by correctly determining the size of
|
||||
the destination buffer. */
|
||||
#define T(size, ...) \
|
||||
(FUNC (sprintf) (buffer (size), __VA_ARGS__), \
|
||||
sink (buffer, ptr))
|
||||
|
||||
/* Return a value in the range [MIN, MAX]. */
|
||||
#define IR(min, max) int_range (min, max)
|
||||
|
||||
/* Return a string whose length is in the range [MIN, MAX] where
|
||||
both MIN and MAX must be digits in the range [0, 9]. */
|
||||
#define SR(min, max) (int_value () < 0 ? s##min : s##max)
|
||||
|
||||
/* Return a wide string whose length is in the range [MIN, MAX] where
|
||||
both MIN and MAX must be digits in the range [0, 9]. */
|
||||
#define WR(min, max) (int_value () < 0 ? ws##min : ws##max)
|
||||
|
||||
void test_narrow_string_with_precision (void)
|
||||
{
|
||||
T (-1, "%.*s", IR ( 0, 1), SR (0, 1));
|
||||
T (-1, "%.*s", IR ( 0, 1), SR (0, 2));
|
||||
T (-1, "%.*s", IR ( 0, 1), SR (0, 3));
|
||||
T (-1, "%.*s", IR ( 0, 1), SR (0, 4));
|
||||
T (-1, "%.*s", IR ( 0, 1), SR (0, 9));
|
||||
T (-1, "%.*s", IR ( 0, 2), SR (0, 9));
|
||||
T (-1, "%.*s", IR ( 0, 3), SR (0, 9));
|
||||
T (-1, "%.*s", IR ( 0, 4), SR (0, 9));
|
||||
T (-1, "%.*s", IR ( 0, 9), SR (0, 9));
|
||||
T (-1, "%.*s", IR ( 0, 99), SR (0, 9));
|
||||
T (-1, "%.*s", IR ( 0, 99), SR (0, x));
|
||||
T (-1, "%.*s", IR ( 0, 99), SR (1, x));
|
||||
T (-1, "%.*s", IR ( 0, 99), SR (x, 1));
|
||||
T (-1, "%.*s", IR ( 0, 99), SR (x, 9));
|
||||
|
||||
T (-1, "%.*s", IR (imax / 3, imax / 2), SR (x, y));
|
||||
|
||||
/* Non-constant zero length string. */
|
||||
T ( 0, "%.*s", IR (imin, -1), SR (0, 0)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*s", IR (imin, 0), SR (0, 0)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*s", IR (-1, 0), SR (0, 0)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*s", IR (-1, 1), SR (0, 0)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*s", IR (-1, 99), SR (0, 0)); /* { dg-warning "writing a terminating nul" } */
|
||||
|
||||
/* String with length between 0 and 1 character. */
|
||||
T ( 0, "%.*s", IR (imin, -1), SR (0, 1)); /* { dg-warning "writing up to 1 byte" } */
|
||||
T ( 0, "%.*s", IR (imin, 0), SR (0, 1)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*s", IR (-2, -1), SR (0, 1)); /* { dg-warning "writing up to 1 byte" } */
|
||||
T ( 0, "%.*s", IR (-2, 0), SR (0, 1)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*s", IR ( 0, 1), SR (0, 1)); /* { dg-warning "writing up to 1 byte" } */
|
||||
T ( 0, "%.*s", IR ( 0, 2), SR (0, 1)); /* { dg-warning "writing up to 1 byte" } */
|
||||
T ( 0, "%.*s", IR ( 0, 99), SR (0, 1)); /* { dg-warning "writing up to 1 byte" } */
|
||||
T ( 0, "%.*s", IR ( 0, imax), SR (0, 1)); /* { dg-warning "writing up to 1 byte" } */
|
||||
T ( 0, "%.*s", IR ( 1, imax), SR (0, 1)); /* { dg-warning "writing up to 1 byte" } */
|
||||
T ( 0, "%.*s", IR ( 9, imax), SR (0, 1)); /* { dg-warning "writing up to 1 byte" } */
|
||||
|
||||
/* String with length between 2 and 3 characters. */
|
||||
T ( 0, "%.*s", IR (imin, -1), SR (2, 3)); /* { dg-warning "writing between 2 and 3 bytes" } */
|
||||
T ( 0, "%.*s", IR (imin, 0), SR (2, 3)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*s", IR (-2, -1), SR (2, 3)); /* { dg-warning "writing between 2 and 3 bytes" } */
|
||||
T ( 0, "%.*s", IR (-2, 0), SR (2, 3)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*s", IR (-2, 1), SR (2, 3)); /* { dg-warning "writing up to 1 byte" } */
|
||||
T ( 0, "%.*s", IR ( 0, 1), SR (2, 3)); /* { dg-warning "writing up to 1 byte" } */
|
||||
T ( 0, "%.*s", IR ( 0, 2), SR (2, 3)); /* { dg-warning "writing up to 2 bytes" } */
|
||||
T ( 0, "%.*s", IR ( 0, 99), SR (2, 3)); /* { dg-warning "writing up to 3 bytes" } */
|
||||
T ( 0, "%.*s", IR ( 0, imax), SR (2, 3)); /* { dg-warning "writing up to 3 bytes" } */
|
||||
T ( 0, "%.*s", IR ( 1, 99), SR (2, 3)); /* { dg-warning "writing between 1 and 3 bytes" } */
|
||||
T ( 0, "%.*s", IR ( 9, 99), SR (2, 3)); /* { dg-warning "writing between 2 and 3 bytes" } */
|
||||
|
||||
T ( 0, "%.*s", IR ( 0, 1), SR (0, 9)); /* { dg-warning "writing up to 1 byte" } */
|
||||
T ( 0, "%.*s", IR ( 0, 2), SR (0, 9)); /* { dg-warning "writing up to 2 bytes" } */
|
||||
T ( 0, "%.*s", IR ( 0, 9), SR (0, 9)); /* { dg-warning "writing up to 9 bytes" } */
|
||||
T ( 0, "%.*s", IR ( 0, 79), SR (0, 9)); /* { dg-warning "writing up to 9 bytes" } */
|
||||
T ( 0, "%.*s", IR ( 1, 2), SR (0, 9)); /* { dg-warning "writing up to 2 bytes" } */
|
||||
T ( 0, "%.*s", IR ( 2, 3), SR (0, 9)); /* { dg-warning "writing up to 3 bytes" } */
|
||||
T ( 0, "%.*s", IR ( 7, 13), SR (0, 9)); /* { dg-warning "writing up to 9 bytes" } */
|
||||
|
||||
/* String between N and unknown number of characters long. */
|
||||
T ( 0, "%.*s", IR (imin, -1), SR (0, x)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*s", IR (imin, -1), SR (1, x)); /* { dg-warning "writing likely 1 or more bytes" } */
|
||||
T ( 1, "%.*s", IR (imin, -1), SR (1, x)); /* { dg-warning "may write a terminating nul" } */
|
||||
T ( 1, "%.*s", IR (imin, -1), SR (8, x)); /* { dg-warning "writing likely 8 or more bytes" } */
|
||||
T ( 1, "%.*s", IR (imin, -1), SR (x, 9)); /* { dg-warning "writing likely 9 or more bytes" } */
|
||||
|
||||
/* Unknown strings. */
|
||||
T ( 1, "%.*s", IR (imin, -1), SR (x, y));
|
||||
T ( 1, "%.*s", IR (imin, 0), SR (x, y));
|
||||
T ( 1, "%.*s", IR ( -99, 1), SR (x, y)); /* { dg-warning "may write a terminating nul" } */
|
||||
T ( 1, "%.*s", IR ( -2, 2), SR (x, y)); /* { dg-warning "may write a terminating nul" } */
|
||||
T ( 1, "%.*s", IR ( -1, 99), SR (x, y)); /* { dg-warning "may write a terminating nul" } */
|
||||
T ( 1, "%.*s", IR ( 0, 99), SR (x, y)); /* { dg-warning "may write a terminating nul" } */
|
||||
T ( 1, "%.*s", IR ( 1, 99), SR (x, y)); /* { dg-warning "may write a terminating nul" } */
|
||||
T ( 1, "%.*s", IR ( 9, 99), SR (x, y)); /* { dg-warning "may write a terminating nul" } */
|
||||
}
|
||||
|
||||
void test_narrow_string_with_width_and_precision (void)
|
||||
{
|
||||
T (-1, "%*.*s", IR ( 0, 1), IR ( 0, 1), SR (0, 1));
|
||||
T (-1, "%*.*s", IR ( 0, 1), IR ( 0, 1), SR (0, 2));
|
||||
T (-1, "%*.*s", IR ( 0, 1), IR ( 0, 1), SR (0, 3));
|
||||
T (-1, "%*.*s", IR ( 0, 1), IR ( 0, 1), SR (0, 4));
|
||||
T (-1, "%*.*s", IR ( 0, 1), IR ( 0, 1), SR (0, 9));
|
||||
T (-1, "%*.*s", IR ( 0, 2), IR ( 0, 2), SR (0, 9));
|
||||
T (-1, "%*.*s", IR ( 0, 3), IR ( 0, 3), SR (0, 9));
|
||||
T (-1, "%*.*s", IR ( 0, 4), IR ( 0, 4), SR (0, 9));
|
||||
T (-1, "%*.*s", IR ( 0, 9), IR ( 0, 9), SR (0, 9));
|
||||
T (-1, "%*.*s", IR ( 0, 99), IR ( 0, 99), SR (0, 9));
|
||||
T (-1, "%*.*s", IR ( 0, 99), IR ( 0, 99), SR (0, x));
|
||||
T (-1, "%*.*s", IR ( 0, 99), IR ( 0, 99), SR (1, x));
|
||||
T (-1, "%*.*s", IR ( 0, 99), IR ( 0, 99), SR (x, 1));
|
||||
T (-1, "%*.*s", IR ( 0, 99), IR ( 0, 99), SR (x, 9));
|
||||
T (-1, "%*.*s", IR (12, 34), IR (45, 67), SR (x, 9));
|
||||
T (-1, "%*.*s", IR (12, 34), IR (45, 67), SR (x, y));
|
||||
|
||||
T (-1, "%*.*s", IR (imax / 5, imax / 4), IR (imax / 3, imax / 2), SR (x, y));
|
||||
|
||||
T (-1, "%*.*s %*.*s",
|
||||
IR (imax / 9, imax / 8), IR (imax / 7, imax / 6), SR (x, y),
|
||||
IR (imax / 5, imax / 4), IR (imax / 3, imax / 2), SR (x, y));
|
||||
|
||||
/* The two directives below combined convert to [INT_MAX, INT_MAX + 1].
|
||||
Since the lower end of the range doesn't exceed INT_MAX no warning
|
||||
is expected. */
|
||||
T (-1, "%*.*s%*.*s",
|
||||
IR (imax - 5, imax - 3), IR (1, 2), SR (x, y),
|
||||
IR ( 5, 6), IR (3, 4), SR (x, y));
|
||||
|
||||
/* The three directives below (the two %s plus the space in between)
|
||||
combined convert to [INT_MAX + 1, INT_MAX + 2]. Since the lower
|
||||
end of the range exceeds INT_MAX a warning is expected. */
|
||||
T (-1, "%*.*s %*.*s", /* { dg-warning "INT_MAX" } */
|
||||
IR (imax - 5, imax - 3), IR (1, 2), SR (x, y),
|
||||
IR ( 5, 6), IR (3, 4), SR (x, y));
|
||||
|
||||
/* Non-constant zero length string. */
|
||||
T ( 0, "%*.*s", IR ( 0, 1), IR (imin, -1), SR (0, 0)); /* { dg-warning "writing up to 1 byte" } */
|
||||
T ( 0, "%*.*s", IR ( 0, 2), IR (imin, -1), SR (0, 0)); /* { dg-warning "writing up to 2 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 0, 3), IR (imin, -1), SR (0, 0)); /* { dg-warning "writing up to 3 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 0, 3), IR ( 0, 1), SR (0, 0)); /* { dg-warning "writing up to 3 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 0, 3), IR ( 0, 1), SR (0, 1)); /* { dg-warning "writing up to 3 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 0, 3), IR ( 0, 2), SR (0, 1)); /* { dg-warning "writing up to 3 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 0, 3), IR ( 0, 3), SR (0, 1)); /* { dg-warning "writing up to 3 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 0, 3), IR ( 0, 1), SR (3, 5)); /* { dg-warning "writing up to 3 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 0, 3), IR ( 0, 2), SR (3, 5)); /* { dg-warning "writing up to 3 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 0, 3), IR ( 0, 3), SR (3, 5)); /* { dg-warning "writing up to 3 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 0, 3), IR ( 0, 4), SR (3, 5)); /* { dg-warning "writing up to 4 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 0, 3), IR ( 0, 5), SR (3, 5)); /* { dg-warning "writing up to 5 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 0, 3), IR ( 0, 6), SR (3, 5)); /* { dg-warning "writing up to 5 bytes" } */
|
||||
|
||||
T ( 0, "%*.*s", IR ( 1, 2), IR ( 0, 1), SR (3, 5)); /* { dg-warning "writing between 1 and 2 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 1, 2), IR ( 0, 2), SR (3, 5)); /* { dg-warning "writing between 1 and 2 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 1, 2), IR ( 0, 3), SR (3, 5)); /* { dg-warning "writing between 1 and 3 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 1, 2), IR ( 0, 4), SR (3, 5)); /* { dg-warning "writing between 1 and 4 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 1, 2), IR ( 0, 5), SR (3, 5)); /* { dg-warning "writing between 1 and 5 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 1, 2), IR ( 0, 6), SR (3, 5)); /* { dg-warning "writing between 1 and 5 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 2, 3), IR ( 0, 6), SR (3, 5)); /* { dg-warning "writing between 2 and 5 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 2, 3), IR ( 1, 6), SR (3, 5)); /* { dg-warning "writing between 2 and 5 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 2, 3), IR ( 2, 6), SR (3, 5)); /* { dg-warning "writing between 2 and 5 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 2, 3), IR ( 3, 6), SR (3, 5)); /* { dg-warning "writing between 3 and 5 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 2, 3), IR ( 4, 6), SR (3, 5)); /* { dg-warning "writing between 3 and 5 bytes" } */
|
||||
T ( 0, "%*.*s", IR ( 2, 3), IR ( 5, 6), SR (3, 5)); /* { dg-warning "writing between 3 and 5 bytes" } */
|
||||
}
|
||||
|
||||
void test_wide_string (void)
|
||||
{
|
||||
T (-1, "%.*ls", IR ( 0, 1), WR (0, 1));
|
||||
T (-1, "%.*ls", IR ( 0, 1), WR (0, 2));
|
||||
T (-1, "%.*ls", IR ( 0, 1), WR (0, 3));
|
||||
T (-1, "%.*ls", IR ( 0, 1), WR (0, 4));
|
||||
T (-1, "%.*ls", IR ( 0, 1), WR (0, 9));
|
||||
T (-1, "%.*ls", IR ( 0, 2), WR (0, 9));
|
||||
T (-1, "%.*ls", IR ( 0, 3), WR (0, 9));
|
||||
T (-1, "%.*ls", IR ( 0, 4), WR (0, 9));
|
||||
T (-1, "%.*ls", IR ( 0, 9), WR (0, 9));
|
||||
T (-1, "%.*ls", IR ( 0, 99), WR (0, 9));
|
||||
T (-1, "%.*ls", IR ( 0, 99), WR (0, x));
|
||||
T (-1, "%.*ls", IR ( 0, 99), WR (1, x));
|
||||
T (-1, "%.*ls", IR ( 0, 99), WR (x, 1));
|
||||
T (-1, "%.*ls", IR ( 0, 99), WR (x, 9));
|
||||
|
||||
/* Non-constant zero length string. */
|
||||
T ( 0, "%.*ls", IR (imin, -1), WR (0, 0)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*ls", IR (imin, 0), WR (0, 0)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*ls", IR (-1, 0), WR (0, 0)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*ls", IR (-1, 1), WR (0, 0)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*ls", IR (-1, 99), WR (0, 0)); /* { dg-warning "writing a terminating nul" } */
|
||||
|
||||
/* String with length between 0 and 1 character. */
|
||||
T ( 0, "%.*ls", IR (imin, -1), WR (0, 1)); /* { dg-warning "writing up to 6 bytes" } */
|
||||
T ( 0, "%.*ls", IR (imin, 0), WR (0, 1)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*ls", IR (-2, -1), WR (0, 1)); /* { dg-warning "writing up to 6 bytes" } */
|
||||
T ( 0, "%.*ls", IR (-2, 0), WR (0, 1)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*ls", IR ( 0, 1), WR (0, 1)); /* { dg-warning "writing up to 1 byte" } */
|
||||
T ( 0, "%.*ls", IR ( 0, 2), WR (0, 1)); /* { dg-warning "writing up to 2 bytes" } */
|
||||
T ( 0, "%.*ls", IR ( 0, 99), WR (0, 1)); /* { dg-warning "writing up to 6 bytes" } */
|
||||
T ( 0, "%.*ls", IR ( 0, imax), WR (0, 1)); /* { dg-warning "writing up to 6 bytes" } */
|
||||
T ( 0, "%.*ls", IR ( 1, imax), WR (0, 1)); /* { dg-warning "writing up to 6 bytes" } */
|
||||
T ( 0, "%.*ls", IR ( 9, imax), WR (0, 1)); /* { dg-warning "writing up to 6 bytes" } */
|
||||
|
||||
/* String with length between 2 and 3 characters. */
|
||||
T ( 0, "%.*ls", IR (imin, -1), WR (2, 3)); /* { dg-warning "writing up to 18 bytes" } */
|
||||
T ( 0, "%.*ls", IR (imin, 0), WR (2, 3)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*ls", IR (-2, -1), WR (2, 3)); /* { dg-warning "writing up to 18 bytes" } */
|
||||
T ( 0, "%.*ls", IR (-2, 0), WR (2, 3)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*ls", IR (-2, 1), WR (2, 3)); /* { dg-warning "writing up to 1 byte" } */
|
||||
T ( 0, "%.*ls", IR ( 0, 1), WR (2, 3)); /* { dg-warning "writing up to 1 byte" } */
|
||||
T ( 0, "%.*ls", IR ( 0, 2), WR (2, 3)); /* { dg-warning "writing up to 2 bytes" } */
|
||||
T ( 0, "%.*ls", IR ( 0, 99), WR (2, 3)); /* { dg-warning "writing up to 18 bytes" } */
|
||||
T ( 0, "%.*ls", IR ( 0, imax), WR (2, 3)); /* { dg-warning "writing up to 18 bytes" } */
|
||||
T ( 0, "%.*ls", IR ( 1, 99), WR (2, 3)); /* { dg-warning "writing up to 18 bytes" } */
|
||||
T ( 0, "%.*ls", IR ( 9, 99), WR (2, 3)); /* { dg-warning "writing up to 18 bytes" } */
|
||||
|
||||
T ( 0, "%.*ls", IR ( 0, 1), WR (0, 9)); /* { dg-warning "writing up to 1 byte" } */
|
||||
T ( 0, "%.*ls", IR ( 0, 2), WR (0, 9)); /* { dg-warning "writing up to 2 bytes" } */
|
||||
T ( 0, "%.*ls", IR ( 0, 9), WR (0, 9)); /* { dg-warning "writing up to 9 bytes" } */
|
||||
T ( 0, "%.*ls", IR ( 0, 53), WR (0, 9)); /* { dg-warning "writing up to 53 bytes" } */
|
||||
T ( 0, "%.*ls", IR ( 0, 55), WR (0, 9)); /* { dg-warning "writing up to 54 bytes" } */
|
||||
T ( 0, "%.*ls", IR ( 1, 2), WR (0, 9)); /* { dg-warning "writing up to 2 bytes" } */
|
||||
T ( 0, "%.*ls", IR ( 2, 3), WR (0, 9)); /* { dg-warning "writing up to 3 bytes" } */
|
||||
T ( 0, "%.*ls", IR ( 7, 13), WR (0, 9)); /* { dg-warning "writing up to 13 bytes" } */
|
||||
|
||||
/* String between N and unknown number of characters long. */
|
||||
T ( 0, "%.*ls", IR (imin, -1), WR (0, x)); /* { dg-warning "writing a terminating nul" } */
|
||||
T ( 0, "%.*ls", IR (imin, -1), WR (1, x)); /* { dg-warning "writing likely 2 or more bytes" } */
|
||||
T ( 1, "%.*ls", IR (imin, -1), WR (1, x)); /* { dg-warning "writing likely 2 or more bytes" } */
|
||||
T ( 1, "%.*ls", IR (imin, -1), WR (8, x)); /* { dg-warning "writing likely 16 or more bytes" } */
|
||||
T ( 1, "%.*ls", IR (imin, -1), WR (x, 9)); /* { dg-warning "writing likely 18 or more bytes" } */
|
||||
|
||||
/* Unknown strings. */
|
||||
T ( 1, "%.*ls", IR (imin, -1), WR (x, y));
|
||||
T ( 1, "%.*ls", IR (imin, 0), WR (x, y));
|
||||
T ( 1, "%.*ls", IR ( -99, 1), WR (x, y)); /* { dg-warning "may write a terminating nul" } */
|
||||
T ( 1, "%.*ls", IR ( -2, 2), WR (x, y)); /* { dg-warning "may write a terminating nul" } */
|
||||
T ( 1, "%.*ls", IR ( -1, 99), WR (x, y)); /* { dg-warning "may write a terminating nul" } */
|
||||
T ( 1, "%.*ls", IR ( 0, 99), WR (x, y)); /* { dg-warning "may write a terminating nul" } */
|
||||
T ( 1, "%.*ls", IR ( 1, 99), WR (x, y)); /* { dg-warning "may write a terminating nul" } */
|
||||
T ( 1, "%.*ls", IR ( 9, 99), WR (x, y)); /* { dg-warning "may write a terminating nul" } */
|
||||
}
|
14
gcc/testsuite/gcc.dg/tree-ssa/pr79275.c
Normal file
14
gcc/testsuite/gcc.dg/tree-ssa/pr79275.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* PR middle-end/79275 - -Wformat-overflow false positive exceeding INT_MAX
|
||||
in glibc sysdeps/posix/tempname.c
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O2 -Wall -Wformat-overflow=1 -ftrack-macro-expansion=0" } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
void f (char *dst, size_t n, const char *s)
|
||||
{
|
||||
if (n < 2 || __INT_MAX__ - 2 < n)
|
||||
n = 2;
|
||||
|
||||
__builtin_sprintf (dst, "%.*s %.*s", (int)n, s, (int)n, s); /* { dg-bogus "INT_MAX" } */
|
||||
}
|
Loading…
Add table
Reference in a new issue