Commit de6aa933 by Martin Sebor Committed by Martin Sebor

PR middle-end/78521 - [7 Regression] incorrect byte count in -Wformat-length...

PR middle-end/78521 - [7 Regression] incorrect byte count in -Wformat-length warning with non-constant width or precision
PR middle-end/78520 - missing warning for snprintf with size greater than INT_MAX

gcc/ChangeLog:

	PR middle-end/78520
	* gimple-ssa-sprintf.c (target_max_value): Remove.
	(target_int_max, target_size_max): Use TYPE_MAX_VALUE.
	(get_width_and_precision): New function.
	(format_integer, format_floating, get_string_length, format_string):
	Correct handling of width and precision with unknown value.
	(format_directive): Add warning.
	(pass_sprintf_length::compute_format_length): Allow for precision
	to consist of a sole period with no asterisk or digits after it.

gcc/testsuite/ChangeLog:

	PR middle-end/78520
	* gcc.dg/tree-ssa/builtin-sprintf-5.c: Add test cases.
	* gcc.dg/tree-ssa/builtin-sprintf-6.c: New test.
	* gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Add test cases.
	* gcc.dg/tree-ssa/builtin-sprintf-warn-3.c: Add test cases.

From-SVN: r242935
parent b3a5bff4
2016-11-28 Martin Sebor <msebor@redhat.com>
PR middle-end/78520
* gimple-ssa-sprintf.c (target_max_value): Remove.
(target_int_max, target_size_max): Use TYPE_MAX_VALUE.
(get_width_and_precision): New function.
(format_integer, format_floating, get_string_length, format_string):
Correct handling of width and precision with unknown value.
(format_directive): Add warning.
(pass_sprintf_length::compute_format_length): Allow for precision
to consist of a sole period with no asterisk or digits after it.
2016-11-28 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/78546
2016-11-28 Martin Sebor <msebor@redhat.com>
PR middle-end/78520
* gcc.dg/tree-ssa/builtin-sprintf-5.c: Add test cases.
* gcc.dg/tree-ssa/builtin-sprintf-6.c: New test.
* gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Add test cases.
* gcc.dg/tree-ssa/builtin-sprintf-warn-3.c: Add test cases.
2016-11-28 Jakub Jelinek <jakub@redhat.com>
PR c++/72808
......
......@@ -44,6 +44,26 @@ void test_arg_int (int i, int n)
for (i = -n; i != n; ++i)
T (8, "%08x", i);
/* As a special case, a precision of zero with an argument of zero
results in zero bytes (unless modified by width). */
T (0, "%.0d", ival (0));
T (0, "%.0i", ival (0));
T (0, "%.0o", ival (0));
T (0, "%.0u", ival (0));
T (0, "%.0x", ival (0));
T (0, "%.*d", 0, ival (0));
T (0, "%.*i", 0, ival (0));
T (0, "%.*o", 0, ival (0));
T (0, "%.*u", 0, ival (0));
T (0, "%.*x", 0, ival (0));
T (1, "%1.0d", ival (0));
T (1, "%1.0i", ival (0));
T (1, "%1.0o", ival (0));
T (1, "%1.0u", ival (0));
T (1, "%1.0x", ival (0));
}
void test_arg_string (const char *s)
......
/* PR middle-end/78476 - snprintf(0, 0, ...) with known arguments not
optimized away
A negative test complementing builtin-sprintf-5.c to verify that calls
to the function that do not return a constant are not optimized away.
{ dg-compile }
{ dg-options "-O2 -fdump-tree-optimized" }
{ dg-require-effective-target int32plus } */
#define CONCAT(a, b) a ## b
#define CAT(a, b) CONCAT (a, b)
#define T(...) \
do { \
int CAT (n, __LINE__) = __builtin_snprintf (0, 0, __VA_ARGS__); \
sink (CAT (n, __LINE__)); \
} while (0)
void sink (int);
static int
int_range (int min, int max)
{
extern int int_value (void);
int val = int_value ();
if (val < min || max < val)
val = min;
return val;
}
#define R(min, max) int_range (min, max)
void test_arg_int (int width, int prec, int i, int n)
{
T ("%i", i);
T ("%1i", i);
T ("%2i", i);
T ("%3i", i);
T ("%4i", i);
T ("%*i", width, 0);
T ("%*i", width, 1);
T ("%*i", width, i);
T ("%.*i", prec, 0);
T ("%.*i", prec, 1);
T ("%.*i", prec, i);
T ("%.*i", 0, i);
T ("%i", R (1, 10));
for (i = -n; i != n; ++i)
T ("%*x", n, i);
}
void test_arg_string (int width, int prec, const char *s)
{
T ("%-s", s);
T ("%1s", s);
T ("%.1s", s);
T ("%*s", width, s);
T ("%.*s", prec, s);
T ("%1.*s", prec, s);
T ("%*.1s", width, s);
T ("%*.*s", width, prec, s);
T ("%*s", width, "123");
T ("%.*s", prec, "123");
T ("%1.*s", prec, "123");
T ("%*.1s", width, "123");
T ("%*.*s", width, prec, "123");
}
/* { dg-final { scan-tree-dump-times "snprintf" 27 "optimized"} } */
/* { dg-do compile } */
/* { dg-options "-std=c99 -O2 -Wformat -Wformat-length=1 -ftrack-macro-expansion=0" } */
typedef __SIZE_TYPE__ size_t;
#ifndef LINE
# define LINE 0
#endif
......@@ -232,3 +234,48 @@ void test_sprintf_chk_range_sshort (signed short *a, signed short *b)
T ( 4, "%i", Ra (998, 999));
T ( 4, "%i", Ra (999, 1000)); /* { dg-warning "may write a terminating nul past the end of the destination" } */
}
/* Verify that destination size in excess of INT_MAX (and, separately,
in excess of the largest object) is diagnosed. The former because
the functions are defined only for output of at most INT_MAX and
specifying a large upper bound defeats the bounds checking (and,
on some implementations such as Solaris, causes the function to
fail. The latter because due to the limit of ptrdiff_t no object
can be larger than PTRDIFF_MAX bytes. */
void test_too_large (char *d, int x, __builtin_va_list va)
{
const size_t imax = __INT_MAX__;
const size_t imax_p1 = imax + 1;
__builtin_snprintf (d, imax, "%c", x);
__builtin_snprintf (d, imax_p1, "%c", x); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." "" { target lp64 } } */
/* { dg-warning "specified destination size \[0-9\]+ is too large" "" { target { ilp32 } } .-1 } */
__builtin_vsnprintf (d, imax, "%c", va);
__builtin_vsnprintf (d, imax_p1, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." { target lp64 } } */
/* { dg-warning "specified destination size \[0-9\]+ is too large" "" { target { ilp32 } } .-1 } */
__builtin___snprintf_chk (d, imax, 0, imax, "%c", x);
__builtin___snprintf_chk (d, imax_p1, 0, imax_p1, "%c", x); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." { target lp64 } } */
/* { dg-warning "specified destination size \[0-9\]+ is too large" "" { target { ilp32 } } .-1 } */
__builtin___vsnprintf_chk (d, imax, 0, imax, "%c", va);
__builtin___vsnprintf_chk (d, imax_p1, 0, imax_p1, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." { target lp64 } } */
/* { dg-warning "specified destination size \[0-9\]+ is too large" "" { target { ilp32 } } .-1 } */
const size_t ptrmax = __PTRDIFF_MAX__;
const size_t ptrmax_m1 = ptrmax - 1;
__builtin_snprintf (d, ptrmax_m1, "%c", x); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." "" { target lp64 } } */
__builtin_snprintf (d, ptrmax, " %c", x); /* { dg-warning "specified destination size \[0-9\]+ is too large" } */
__builtin_vsnprintf (d, ptrmax_m1, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." "" { target lp64 } } */
__builtin_vsnprintf (d, ptrmax, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ is too large" } */
__builtin___snprintf_chk (d, ptrmax_m1, 0, ptrmax_m1, "%c", x); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." "" { target lp64 } } */
__builtin___snprintf_chk (d, ptrmax, 0, ptrmax, "%c", x); /* { dg-warning "specified destination size \[0-9\]+ is too large" } */
__builtin___vsnprintf_chk (d, ptrmax_m1, 0, ptrmax_m1, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." "" { target lp64 } } */
__builtin___vsnprintf_chk (d, ptrmax, 0, ptrmax, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ is too large" } */
}
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