Commit ebee1eb9 by Martin Sebor Committed by Martin Sebor

PR middle-end/79275 - -Wformat-overflow false positive exceeding INT_MAX in…

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
parent 92d8bb06
2017-02-02 Martin Sebor <msebor@redhat.com> 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. * doc/invoke.texi (-maccumulate-args): Fix bad grammar.
PR middle-end/32003 PR middle-end/32003
......
...@@ -1832,10 +1832,11 @@ get_string_length (tree str) ...@@ -1832,10 +1832,11 @@ get_string_length (tree str)
} }
else 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 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.likely = res.range.min ? res.range.min : warn_level > 1;
res.range.min = 0;
} }
res.range.unlikely = res.range.max; res.range.unlikely = res.range.max;
...@@ -1986,43 +1987,89 @@ format_string (const directive &dir, tree arg) ...@@ -1986,43 +1987,89 @@ format_string (const directive &dir, tree arg)
} }
else else
{ {
/* For a '%s' and '%ls' directive with a non-constant string, /* For a '%s' and '%ls' directive with a non-constant string (either
the minimum number of characters is the greater of WIDTH one of a number of strings of known length or an unknown string)
and either 0 in mode 1 or the smaller of PRECISION and 1 the minimum number of characters is lesser of PRECISION[0] and
in mode 2, and the maximum is PRECISION or -1 to disable the length of the shortest known string or zero, and the maximum
tracking. */ 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) 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 ()) 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) else if ((unsigned HOST_WIDE_INT)dir.prec[0] < slen.range.min)
{ res.range.min = dir.prec[0];
slen.range.min = dir.prec[0];
slen.range.likely = slen.range.min;
}
/* Make both maxima no greater than the upper bound of precision. */
if ((unsigned HOST_WIDE_INT)dir.prec[1] < slen.range.max if ((unsigned HOST_WIDE_INT)dir.prec[1] < slen.range.max
|| slen.range.max >= target_int_max ()) || slen.range.max >= target_int_max ())
{ {
slen.range.max = dir.prec[1]; res.range.max = dir.prec[1];
slen.range.likely = slen.range.max; 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 ()) else if (slen.range.min >= target_int_max ())
{ {
slen.range.min = 0; res.range.min = 0;
slen.range.max = HOST_WIDE_INT_MAX; res.range.max = HOST_WIDE_INT_MAX;
/* At level one strings of unknown length are assumed to be /* At level 1 strings of unknown length are assumed to be
empty, while at level 1 they are assumed to be one byte empty, while at level 1 they are assumed to be one byte
long. */ 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.unlikely = res.range.max;
res.range = slen.range;
res.knownrange = slen.knownrange;
} }
/* Bump up the byte counters if WIDTH is greater. */ /* Bump up the byte counters if WIDTH is greater. */
......
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> 2017-02-02 Aaron Sawdey <acsawdey@linux.vnet.ibm.com>
* gcc.dg/sms-8.c: Update options for powerpc*-*-*. * gcc.dg/sms-8.c: Update options for powerpc*-*-*.
......
/* 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" } */
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment