Commit ee92e7ba by Martin Sebor Committed by Martin Sebor

PR c/53562 - Add -Werror= support for -D_FORTIFY_SOURCE / __builtin___memcpy_chk

PR c/53562 - Add -Werror= support for -D_FORTIFY_SOURCE / __builtin___memcpy_chk
PR middle-end/77784 - duplicate warning for snprintf when n > object size
PR middle-end/78149 - missing warning on strncpy buffer overflow due to an excessive bound
PR middle-end/78138 - missing warnings on buffer overflow with non-constant source length

gcc/c-family/ChangeLog:

	PR c/53562
	PR middle-end/77784
	PR middle-end/78149
	PR middle-end/78138
	* c.opt (-Wstringop-overflow): New option.

gcc/ChangeLog:

	PR middle-end/77784
	PR middle-end/78149
	PR middle-end/78138
	
	* builtins.c (expand_builtin_strcat, expand_builtin_strncat): New
	functions.
	(compute_dest_size, get_size_range, check_sizes, check_strncat_sizes)
	(check_memop_sizes): Same.
	(expand_builtin_memcpy): Call check memop_sizes.
	(expand_builtin_mempcpy): Same.
	(expand_builtin_memset): Same,
	(expand_builtin_bzero): Same.
	(expand_builtin_memory_chk): Call check_sizes.
	(expand_builtin_strcpy): Same.
	(expand_builtin_strncpy): Same.
	(maybe_emit_sprintf_chk_warning): Same.
	(expand_builtin): Handle strcat and strncat.
	(fini_object_sizes): Reset pointers.
	(compute_object_size): New function.
	* gimple-ssa-sprintf.c (pass_sprintf_length::handle_gimple_call):
	Avoid issuing warnings also issued during built-in expansion.
	* doc/invoke.texi (Warning Options): Document -Wstringop-overflow.

gcc/testsuite/ChangeLog:

	PR middle-end/77784
	PR middle-end/78149
	PR middle-end/78138

	* c-c++-common/Wsizeof-pointer-memaccess2.c: Adjust expected diagnostic.
	* g++.dg/ext/builtin-object-size3.C (bar): Same.
	* g++.dg/ext/strncpy-chk1.C: Same.
	* g++.dg/opt/memcpy1.C: Same.
	* g++.dg/torture/Wsizeof-pointer-memaccess1.C: Same.
	* gcc.c-torture/compile/pr55569.c: Disable -Wstringop-overflow.
	* gcc.dg/Wobjsize-1.c: Adjust expected diagnostic.
	* gcc.dg/attr-alloc_size.c: Same.
	* gcc.dg/builtin-stringop-chk-1.c: Adjust expected diagnostic.
	* gcc.dg/builtin-stringop-chk-2.c: Same.
	* gcc.dg/builtin-stringop-chk-4.c: New test.
	* gcc.dg/builtin-strncat-chk-1.c: Adjust expected diagnostic.
	* gcc.dg/memcpy-2.c: Same.
	* gcc.dg/pr40340-1.c: Same.
	* gcc.dg/pr40340-2.c (main): Same.
	* gcc.dg/pr40340-5.c (main): Same.
	* gcc.dg/torture/Wsizeof-pointer-memaccess1.c: Same.
	* gcc.dg/torture/pr71132.c: Disable -Wstringop-overflow.
	* gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Adjust text of expected
	warning.
	* gfortran.dg/char_length_3.f90: Prune expected warnings.
	* gfortran.dg/pr38868.f: Add expected warnings.

From-SVN: r243419
parent fc3f36f9
2016-12-07 Martin Sebor <msebor@redhat.com>
PR middle-end/77784
PR middle-end/78149
PR middle-end/78138
* builtins.c (expand_builtin_strcat, expand_builtin_strncat): New
functions.
(compute_dest_size, get_size_range, check_sizes, check_strncat_sizes)
(check_memop_sizes): Same.
(expand_builtin_memcpy): Call check memop_sizes.
(expand_builtin_mempcpy): Same.
(expand_builtin_memset): Same,
(expand_builtin_bzero): Same.
(expand_builtin_memory_chk): Call check_sizes.
(expand_builtin_strcpy): Same.
(expand_builtin_strncpy): Same.
(maybe_emit_sprintf_chk_warning): Same.
(expand_builtin): Handle strcat and strncat.
(fini_object_sizes): Reset pointers.
(compute_object_size): New function.
* gimple-ssa-sprintf.c (pass_sprintf_length::handle_gimple_call):
Avoid issuing warnings also issued during built-in expansion.
* doc/invoke.texi (Warning Options): Document -Wstringop-overflow.
2016-12-07 Michael Meissner <meissner@linux.vnet.ibm.com>
PR target/72717
2016-12-07 Martin Sebor <msebor@redhat.com>
PR c/53562
PR middle-end/77784
PR middle-end/78149
PR middle-end/78138
* c.opt (-Wstringop-overflow): New option.
2016-12-02 Maxim Ostapenko <m.ostapenko@samsung.com>
* c-attribs.c (asan odr indicator): New attribute.
......
......@@ -684,6 +684,16 @@ Wsizeof-array-argument
C ObjC C++ ObjC++ Var(warn_sizeof_array_argument) Warning Init(1)
Warn when sizeof is applied on a parameter declared as an array.
Wstringop-overflow
C ObjC C++ ObjC++ Warning Alias(Wstringop-overflow=, 2, 0)
Warn about buffer overflow in string manipulation functions like memcpy
and strcpy.
Wstringop-overflow=
C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_stringop_overflow) Init(2) Warning
Under the control of Object Size type, warn about buffer overflow in string
manipulation functions like memcpy and strcpy.
Wsuggest-attribute=format
C ObjC C++ ObjC++ Var(warn_suggest_attribute_format) Warning
Warn about functions which might be candidates for format attributes.
......
......@@ -304,6 +304,7 @@ Objective-C and Objective-C++ Dialects}.
-Wsizeof-pointer-memaccess -Wsizeof-array-argument @gol
-Wstack-protector -Wstack-usage=@var{len} -Wstrict-aliasing @gol
-Wstrict-aliasing=n -Wstrict-overflow -Wstrict-overflow=@var{n} @gol
-Wstringop-overflow=@var{n} @gol
-Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{]} @gol
-Wsuggest-final-types @gol -Wsuggest-final-methods -Wsuggest-override @gol
-Wmissing-format-attribute -Wsubobject-linkage @gol
......@@ -4936,6 +4937,86 @@ comparisons, so this warning level gives a very large number of
false positives.
@end table
@item -Wstringop-overflow
@itemx -Wstringop-overflow=@var{type}
@opindex Wstringop-overflow
@opindex Wno-stringop-overflow
Warn for calls to string manipulation functions such as @code{memcpy} and
@code{strcpy} that are determined to overflow the destination buffer. The
optional argument is one greater than the type of Object Size Checking to
perform to determine the size of the destination. @xref{Object Size Checking}.
The argument is meaningful only for functions that operate on character arrays
but not for raw memory functions like @code{memcpy} which always make use
of Object Size type-0. The option also warns for calls that specify a size
in excess of the largest possible object or at most @code{SIZE_MAX / 2} bytes.
The option produces the best results with optimization enabled but can detect
a small subset of simple buffer overflows even without optimization in
calls to the GCC built-in functions like @code{__builtin_memcpy} that
correspond to the standard functions. In any case, the option warns about
just a subset of buffer overflows detected by the corresponding overflow
checking built-ins. For example, the option will issue a warning for
the @code{strcpy} call below because it copies at least 5 characters
(the string @code{"blue"} including the terminating NUL) into the buffer
of size 4.
@smallexample
enum Color @{ blue, purple, yellow @};
const char* f (enum Color clr)
@{
static char buf [4];
const char *str;
switch (clr)
@{
case blue: str = "blue"; break;
case purple: str = "purple"; break;
case yellow: str = "yellow"; break;
@}
return strcpy (buf, str); // warning here
@}
@end smallexample
Option @option{-Wstringop-overflow=2} is enabled by default.
@table @gcctabopt
@item -Wstringop-overflow
@item -Wstringop-overflow=1
@opindex Wstringop-overflow
@opindex Wno-stringop-overflow
The @option{-Wstringop-overflow=1} option uses type-zero Object Size Checking
to determine the sizes of destination objects. This is the default setting
of the option. At this setting the option will not warn for writes past
the end of subobjects of larger objects accessed by pointers unless the
size of the largest surrounding object is known. When the destination may
be one of several objects it is assumed to be the largest one of them. On
Linux systems, when optimization is enabled at this setting the option warns
for the same code as when the @code{_FORTIFY_SOURCE} macro is defined to
a non-zero value.
@item -Wstringop-overflow=2
The @option{-Wstringop-overflow=2} option uses type-one Object Size Checking
to determine the sizes of destination objects. At this setting the option
will warn about overflows when writing to members of the largest complete
objects whose exact size is known. It will, however, not warn for excessive
writes to the same members of unknown objects referenced by pointers since
they may point to arrays containing unknown numbers of elements.
@item -Wstringop-overflow=3
The @option{-Wstringop-overflow=3} option uses type-two Object Size Checking
to determine the sizes of destination objects. At this setting the option
warns about overflowing the smallest object or data member. This is the
most restrictive setting of the option that may result in warnings for safe
code.
@item -Wstringop-overflow=4
The @option{-Wstringop-overflow=4} option uses type-three Object Size Checking
to determine the sizes of destination objects. At this setting the option
will warn about overflowing any data members, and when the destination is
one of several objects it uses the size of the largest of them to decide
whether to issue a warning. Similarly to @option{-Wstringop-overflow=3} this
setting of the option may result in warnings for benign code.
@end table
@item -Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{]}
@opindex Wsuggest-attribute=
@opindex Wno-suggest-attribute=
......
......@@ -774,7 +774,23 @@ get_width_and_precision (const conversion_spec &spec,
if (spec.star_width)
{
if (TREE_CODE (spec.star_width) == INTEGER_CST)
width = abs (tree_to_shwi (spec.star_width));
{
width = tree_to_shwi (spec.star_width);
if (width < 0)
{
if (width == HOST_WIDE_INT_MIN)
{
/* Avoid undefined behavior due to negating a minimum.
This case will be diagnosed since it will result in
more than INT_MAX bytes on output, either by the
directive itself (when INT_MAX < HOST_WIDE_INT_MAX)
or by the format function itself. */
width = HOST_WIDE_INT_MAX;
}
else
width = -width;
}
}
else
width = HOST_WIDE_INT_MIN;
}
......@@ -1261,9 +1277,9 @@ format_floating (const conversion_spec &spec, int width, int prec)
res.range.min = 2 + (prec < 0 ? 6 : prec);
/* Compute the maximum just once. */
static const int f_max[] = {
format_floating_max (double_type_node, 'f'),
format_floating_max (long_double_type_node, 'f')
const int f_max[] = {
format_floating_max (double_type_node, 'f', prec),
format_floating_max (long_double_type_node, 'f', prec)
};
res.range.max = width == INT_MIN ? HOST_WIDE_INT_MAX : f_max [ldbl];
......@@ -1279,9 +1295,9 @@ format_floating (const conversion_spec &spec, int width, int prec)
res.range.min = 2 + (prec < 0 ? 6 : prec);
/* Compute the maximum just once. */
static const int g_max[] = {
format_floating_max (double_type_node, 'g'),
format_floating_max (long_double_type_node, 'g')
const int g_max[] = {
format_floating_max (double_type_node, 'g', prec),
format_floating_max (long_double_type_node, 'g', prec)
};
res.range.max = width == INT_MIN ? HOST_WIDE_INT_MAX : g_max [ldbl];
......@@ -2743,19 +2759,27 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
{
dstsize = tree_to_uhwi (size);
/* No object can be larger than SIZE_MAX bytes (half the address
space) on the target. This imposes a limit that's one byte
less than that.
space) on the target.
The functions are defined only for output of at most INT_MAX
bytes. Specifying a bound in excess of that limit effectively
defeats the bounds checking (and on some implementations such
as Solaris cause the function to fail with EINVAL). */
if (dstsize >= target_size_max () / 2)
warning_at (gimple_location (info.callstmt), OPT_Wformat_length_,
"specified destination size %wu is too large",
dstsize);
if (dstsize > target_size_max () / 2)
{
/* Avoid warning if -Wstringop-overflow is specified since
it also warns for the same thing though only for the
checking built-ins. */
if ((idx_objsize == HOST_WIDE_INT_M1U
|| !warn_stringop_overflow))
warning_at (gimple_location (info.callstmt),
OPT_Wformat_length_,
"specified bound %wu exceeds maximum object size "
"%wu",
dstsize, target_size_max () / 2);
}
else if (dstsize > target_int_max ())
warning_at (gimple_location (info.callstmt), OPT_Wformat_length_,
"specified destination size %wu exceeds %<INT_MAX %>",
"specified bound %wu exceeds %<INT_MAX %>",
dstsize);
}
else if (TREE_CODE (size) == SSA_NAME)
......@@ -2800,10 +2824,15 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
info.objsize = dstsize < objsize ? dstsize : objsize;
if (info.bounded
&& dstsize < target_size_max () / 2 && objsize < dstsize)
&& dstsize < target_size_max () / 2 && objsize < dstsize
/* Avoid warning if -Wstringop-overflow is specified since
it also warns for the same thing though only for the
checking built-ins. */
&& (idx_objsize == HOST_WIDE_INT_M1U
|| !warn_stringop_overflow))
{
warning_at (gimple_location (info.callstmt), OPT_Wformat_length_,
"specified size %wu exceeds the size %wu "
"specified bound %wu exceeds the size %wu "
"of the destination object", dstsize, objsize);
}
}
......
2016-12-07 Martin Sebor <msebor@redhat.com>
PR middle-end/77784
PR middle-end/78149
PR middle-end/78138
* c-c++-common/Wsizeof-pointer-memaccess2.c: Adjust expected diagnostic.
* g++.dg/ext/builtin-object-size3.C (bar): Same.
* g++.dg/ext/strncpy-chk1.C: Same.
* g++.dg/opt/memcpy1.C: Same.
* g++.dg/torture/Wsizeof-pointer-memaccess1.C: Same.
* gcc.c-torture/compile/pr55569.c: Disable -Wstringop-overflow.
* gcc.dg/Wobjsize-1.c: Adjust expected diagnostic.
* gcc.dg/attr-alloc_size.c: Same.
* gcc.dg/builtin-stringop-chk-1.c: Adjust expected diagnostic.
* gcc.dg/builtin-stringop-chk-2.c: Same.
* gcc.dg/builtin-stringop-chk-4.c: New test.
* gcc.dg/builtin-strncat-chk-1.c: Adjust expected diagnostic.
* gcc.dg/memcpy-2.c: Same.
* gcc.dg/pr40340-1.c: Same.
* gcc.dg/pr40340-2.c (main): Same.
* gcc.dg/pr40340-5.c (main): Same.
* gcc.dg/torture/Wsizeof-pointer-memaccess1.c: Same.
* gcc.dg/torture/pr71132.c: Disable -Wstringop-overflow.
* gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Adjust text of expected
warning.
* gfortran.dg/char_length_3.f90: Prune expected warnings.
* gfortran.dg/pr38868.f: Add expected warnings.
2016-12-07 Michael Meissner <meissner@linux.vnet.ibm.com>
PR target/72717
......
......@@ -481,4 +481,4 @@ f4 (char *x, char **y, int z, char w[64])
stpncpy (x, s3, sizeof (s3));
}
/* { dg-prune-output "\[\n\r\]*will always overflow\[\n\r\]*" } */
/* { dg-prune-output "\[\n\r\]*writing\[\n\r\]*" } */
......@@ -20,7 +20,7 @@ bar ()
{
int *p = new int;
int *q = new int[4];
MEMCPY (p, "abcdefghijklmnopqrstuvwxyz", sizeof (int) + 1); // { dg-warning "will always overflow destination buffer" }
MEMCPY (q, "abcdefghijklmnopqrstuvwxyz", 4 * sizeof (int) + 1); // { dg-warning "will always overflow destination buffer" }
MEMCPY (p, "abcdefghijklmnopqrstuvwxyz", sizeof (int) + 1); // { dg-warning "writing" }
MEMCPY (q, "abcdefghijklmnopqrstuvwxyz", 4 * sizeof (int) + 1); // { dg-warning "writing" }
baz (p, q);
}
......@@ -9,7 +9,7 @@ struct B { char z[50]; };
inline void
foo (char *dest, const char *__restrict src, __SIZE_TYPE__ n)
{
__builtin___strncpy_chk (dest, src, n, __builtin_object_size (dest, 0)); // { dg-warning "will always overflow" }
__builtin___strncpy_chk (dest, src, n, __builtin_object_size (dest, 0)); // { dg-warning "specified bound 36 exceeds the size 35 of the destination" }
}
void bar (const char *, int);
......
......@@ -59,7 +59,10 @@ namespace CS
}
uint8 Clip ()
{
__builtin_memcpy (this->OutP, InP, OutV * sizeof (csVector2));
// OutV is initialized to SIZE_MAX in the ctor above causing
// the multiplication below to produce a very large number
// in excess of the maximum possible object size (SIZE_MAX/2).
__builtin_memcpy (this->OutP, InP, OutV * sizeof (csVector2)); // { dg-warning "specified size \[0-9\]+ exceeds maximum object size" }
}
};
}
......
......@@ -713,4 +713,4 @@ f4 (char *x, char **y, int z, char w[64])
return z;
}
// { dg-prune-output "\[\n\r\]*will always overflow\[\n\r\]*" }
// { dg-prune-output "\[\n\r\]*overflows\[\n\r\]*" }
// Test -Wsizeof-pointer-memaccess warnings.
// { dg-do compile }
// { dg-options "-Wall -Wno-sizeof-array-argument" }
// Test just twice, once with -O0 non-fortified, once with -O2 fortified.
// { dg-options "-Wall -Wno-sizeof-array-argument -Wno-stringop-overflow" }
// Test just twice, once with -O0 non-fortified, once with -O2 fortified,
// suppressing buffer overflow warnings.
// { dg-skip-if "" { *-*-* } { "*" } { "-O0" "-O2" } }
// { dg-skip-if "" { *-*-* } { "-flto" } { "" } }
......
/* { dg-options "-ftree-vectorize" } */
/* { dg-options "-Wno-stringop-overflow -ftree-vectorize" } */
int *bar (void);
void
......@@ -6,6 +6,10 @@ foo (void)
{
long x;
int *y = bar ();
for (x = -1 / sizeof (int); x; --x, ++y)
*y = 0;
/* The loop below may be optimized to a call to memset with a size
that's in excess of the maximum object size. This is diagnosed
by the -Wstringop-overflow option. */
for (x = -1 / sizeof (int); x; --x, ++y)
*y = 0;
}
......@@ -10,6 +10,6 @@ int main(int argc, char **argv)
return 0;
}
/* { dg-warning "will always overflow destination buffer" "" { target *-*-* } 6 } */
/* { dg-warning "writing" "" { target *-*-* } 6 } */
/* { dg-message "file included" "included" { target *-*-* } 0 } */
/* { dg-message "inlined from" "inlined" { target *-*-* } 0 } */
......@@ -22,15 +22,15 @@ test (void)
strcpy (p, "Hello");
p = malloc1 (6);
strcpy (p, "Hello");
strcpy (p, "Hello World"); /* { dg-warning "will always overflow" "strcpy" } */
strcpy (p, "Hello World"); /* { dg-warning "writing" "strcpy" } */
p = malloc2 (__INT_MAX__ >= 1700000 ? 424242 : __INT_MAX__ / 4, 6);
strcpy (p, "World");
strcpy (p, "Hello World"); /* { dg-warning "will always overflow" "strcpy" } */
strcpy (p, "Hello World"); /* { dg-warning "writing" "strcpy" } */
p = calloc1 (2, 5);
strcpy (p, "World");
strcpy (p, "Hello World"); /* { dg-warning "will always overflow" "strcpy" } */
strcpy (p, "Hello World"); /* { dg-warning "writing" "strcpy" } */
p = calloc2 (2, __INT_MAX__ >= 1700000 ? 424242 : __INT_MAX__ / 4, 5);
strcpy (p, "World");
strcpy (p, "Hello World"); /* { dg-warning "will always overflow" "strcpy" } */
strcpy (p, "Hello World"); /* { dg-warning "writing" "strcpy" } */
}
......@@ -8,7 +8,10 @@
extern void abort (void);
#include "../gcc.c-torture/execute/builtins/chk.h"
#include <stdarg.h>
#define va_list __builtin_va_list
#define va_start __builtin_va_start
#define va_end __builtin_va_end
volatile void *vx;
char buf1[20];
......@@ -22,60 +25,61 @@ test (int arg, ...)
char *p = &buf1[10], *q;
memcpy (&buf2[19], "ab", 1);
memcpy (&buf2[19], "ab", 2); /* { dg-warning "will always overflow" "memcpy" } */
memcpy (&buf2[19], "ab", 2); /* { dg-warning "writing 2 bytes into a region of size 1" "memcpy" } */
vx = mempcpy (&buf2[19], "ab", 1);
vx = mempcpy (&buf2[19], "ab", 2); /* { dg-warning "will always overflow" "mempcpy" } */
vx = mempcpy (&buf2[19], "ab", 2); /* { dg-warning "writing 2 " "mempcpy" } */
memmove (&buf2[18], &buf1[10], 2);
memmove (&buf2[18], &buf1[10], 3); /* { dg-warning "will always overflow" "memmove" } */
memmove (&buf2[18], &buf1[10], 3); /* { dg-warning "writing 3 " "memmove" } */
memset (&buf2[16], 'a', 4);
memset (&buf2[15], 'b', 6); /* { dg-warning "will always overflow" "memset" } */
memset (&buf2[15], 'b', 6); /* { dg-warning "writing 6 " "memset" } */
strcpy (&buf2[18], "a");
strcpy (&buf2[18], "ab"); /* { dg-warning "will always overflow" "strcpy" } */
strcpy (&buf2[18], "ab"); /* { dg-warning "writing 3 " "strcpy" } */
vx = stpcpy (&buf2[18], "a");
vx = stpcpy (&buf2[18], "ab"); /* { dg-warning "will always overflow" "stpcpy" } */
vx = stpcpy (&buf2[18], "ab"); /* { dg-warning "writing 3" "stpcpy" } */
strncpy (&buf2[18], "a", 2);
strncpy (&buf2[18], "a", 3); /* { dg-warning "will always overflow" "strncpy" } */
strncpy (&buf2[18], "a", 3); /* { dg-warning "specified bound 3 exceeds the size 2 of the destination" "strncpy" } */
strncpy (&buf2[18], "abc", 2);
strncpy (&buf2[18], "abc", 3); /* { dg-warning "will always overflow" "strncpy" } */
strncpy (&buf2[18], "abc", 3); /* { dg-warning "specified bound 3 exceeds the size 2 of the destination" "strncpy" } */
memset (buf2, '\0', sizeof (buf2));
strcat (&buf2[18], "a");
memset (buf2, '\0', sizeof (buf2));
strcat (&buf2[18], "ab"); /* { dg-warning "will always overflow" "strcat" } */
strcat (&buf2[18], "ab"); /* { dg-warning "writing 3 " "strcat" } */
sprintf (&buf2[18], "%s", buf1);
sprintf (&buf2[18], "%s", "a");
sprintf (&buf2[18], "%s", "ab"); /* { dg-warning "will always overflow" "sprintf" } */
sprintf (&buf2[18], "%s", "ab"); /* { dg-warning "writing 3 " "sprintf" } */
sprintf (&buf2[18], "a");
sprintf (&buf2[18], "ab"); /* { dg-warning "will always overflow" "sprintf" } */
sprintf (&buf2[18], "ab"); /* { dg-warning "writing 3 " "sprintf" } */
snprintf (&buf2[18], 2, "%d", x);
/* N argument to snprintf is the size of the buffer.
Although this particular call wouldn't overflow buf2,
incorrect buffer size was passed to it and therefore
we want a warning and runtime failure. */
snprintf (&buf2[18], 3, "%d", x); /* { dg-warning "will always overflow" "snprintf" } */
snprintf (&buf2[18], 3, "%d", x); /* { dg-warning "specified bound 3 exceeds the size 2 of the destination" "snprintf" } */
va_start (ap, arg);
vsprintf (&buf2[18], "a", ap);
va_end (ap);
va_start (ap, arg);
vsprintf (&buf2[18], "ab", ap); /* { dg-warning "will always overflow" "vsprintf" } */
vsprintf (&buf2[18], "ab", ap); /* { dg-warning "writing 3" "vsprintf" } */
va_end (ap);
va_start (ap, arg);
vsnprintf (&buf2[18], 2, "%s", ap);
va_end (ap);
va_start (ap, arg);
/* See snprintf above. */
vsnprintf (&buf2[18], 3, "%s", ap); /* { dg-warning "will always overflow" "vsnprintf" } */
vsnprintf (&buf2[18], 3, "%s", ap); /* { dg-warning "specified bound 3 exceeds the size 2 of the destination" "vsnprintf" } */
va_end (ap);
p = p + 10;
memset (p, 'd', 0);
q = strcpy (p, ""); /* { dg-warning "will always overflow" "strcpy" } */
q = strcpy (p, ""); /* { dg-warning "writing 1 " "strcpy" } */
/* This invokes undefined behavior, since we are past the end of buf1. */
p = p + 10;
memset (p, 'd', 1); /* { dg-warning "will always overflow" "memset" } */
memset (p, 'd', 1); /* { dg-warning "writing 1 " "memset" } */
memset (q, 'd', 0);
memset (q, 'd', 1); /* { dg-warning "will always overflow" "memset" } */
memset (q, 'd', 1); /* { dg-warning "writing 1 " "memset" } */
q = q - 10;
memset (q, 'd', 10);
}
......@@ -90,26 +94,26 @@ void
test2 (const H h)
{
char c;
strncpy (&c, str, 3); /* { dg-warning "will always overflow" "strncpy" } */
strncpy (&c, str, 3); /* { dg-warning "specified bound 3 exceeds the size 1 of the destination" "strncpy" } */
struct { char b[4]; } x;
sprintf (x.b, "%s", "ABCD"); /* { dg-warning "will always overflow" "sprintf" } */
sprintf (x.b, "%s", "ABCD"); /* { dg-warning "writing 5" "sprintf" } */
unsigned int i;
memcpy (&i, &h, sizeof (h)); /* { dg-warning "will always overflow" "memcpy" } */
memcpy (&i, &h, sizeof (h)); /* { dg-warning "writing 16 " "memcpy" } */
unsigned char buf[21];
memset (buf + 16, 0, 8); /* { dg-warning "will always overflow" "memset" } */
memset (buf + 16, 0, 8); /* { dg-warning "writing 8 " "memset" } */
typedef struct { int i, j, k, l; } S;
S *s[3];
memset (s, 0, sizeof (S) * 3); /* { dg-warning "will always overflow" "memset" } */
memset (s, 0, sizeof (S) * 3); /* { dg-warning "writing 48 " "memset" } */
struct T { char a[8]; char b[4]; char c[10]; } t;
stpcpy (t.c,"Testing..."); /* { dg-warning "will always overflow" "stpcpy" } */
stpcpy (t.c,"Testing..."); /* { dg-warning "writing" "stpcpy" } */
char b1[7];
char b2[4];
memset (b1, 0, sizeof (b1));
memset (b2, 0, sizeof (b1)); /* { dg-warning "will always overflow" "memset" } */
memset (b2, 0, sizeof (b1)); /* { dg-warning "writing 7" "memset" } */
}
......@@ -6,7 +6,7 @@
/* { dg-options "-O2 -ftrack-macro-expansion=0" } */
#include "../gcc.c-torture/execute/builtins/chk.h"
void *bar (int);
extern void *malloc (__SIZE_TYPE__);
......@@ -115,7 +115,7 @@ baz (const struct A *x, const unsigned char *z)
else
do
{
memcpy (e, d, 513); /* { dg-warning "will always overflow" "memcpy" } */
memcpy (e, d, 513); /* { dg-warning "writing" "memcpy" } */
e += 4;
}
while (--h);
......
/* Test exercising -Wrawmem-overflow and -Wstringop-overflow warnings. */
/* { dg-do compile } */
/* { dg-options "-O2 -Wstringop-overflow=1" } */
#define offsetof(type, mem) __builtin_offsetof (type, mem)
/* Return the number of bytes from member MEM of TYPE to the end
of object OBJ. */
#define offsetfrom(type, obj, mem) (sizeof (obj) - offsetof (type, mem))
typedef __SIZE_TYPE__ size_t;
extern void* memcpy (void*, const void*, size_t);
extern void* memset (void*, int, __SIZE_TYPE__);
struct A { char a, b; };
struct B { struct A a; char c, d; };
/* Function to call to "escape" pointers from tests below to prevent
GCC from assuming the values of the objects they point to stay
the unchanged. */
void escape (void*, ...);
/* Function to "generate" a random number each time it's called. Declared
(but not defined) and used to prevent GCC from making assumptions about
their values based on the variables uses in the tested expressions. */
size_t random_unsigned_value (void);
/* Return a random unsigned value between MIN and MAX. */
static inline size_t
range (size_t min, size_t max)
{
const size_t val = random_unsigned_value ();
return val < min || max < val ? min : val;
}
/* Verify that writing past the end of a local array is diagnosed. */
void test_memop_warn_local (const void *src)
{
size_t n;
n = range (8, 32);
struct A a[2];
memcpy (a, src, n); /* { dg-warning "writing between 8 and 32 bytes into a region of size 4 overflows the destination" } */
escape (a, src);
/* At -Wrawmem-overflow=1 the destination is considered to be
the whole array and its size is therefore sizeof a. */
memcpy (&a[0], src, n); /* { dg-warning "writing between 8 and 32 bytes into a region of size 4 overflows the destination" } */
escape (a, src);
/* Verify the same as above but by writing into the first mmeber
of the first element of the array. */
memcpy (&a[0].a, src, n); /* { dg-warning "writing between 8 and 32 bytes into a region of size 4 overflows the destination" } */
escape (a, src);
n = range (12, 32);
struct B b[2];
memcpy (&b[0], src, n); /* { dg-warning "writing between 12 and 32 bytes into a region of size 8 overflows the destination" } */
escape (b);
/* The following idiom of clearing multiple members of a struct is
used in a few places in the Linux kernel. Verify that a warning
is issued for it when it writes past the end of the array object. */
memset (&b[0].a.b, 0, offsetfrom (struct B, b, a.b) + 1); /* { dg-warning "writing 8 bytes into a region of size 7" } */
escape (b);
memset (&b->a.b, 0, offsetfrom (struct B, b, a.b) + 1); /* { dg-warning "writing 8 bytes into a region of size 7" } */
escape (b);
memset (&b[0].c, 0, offsetfrom (struct B, b, c) + 1); /* { dg-warning "writing 7 bytes into a region of size 6" } */
escape (b);
memset (&b->c, 0, offsetfrom (struct B, b, c) + 1); /* { dg-warning "writing 7 bytes into a region of size 6" } */
escape (b);
memset (&b[0].d, 0, offsetfrom (struct B, b, d) + 1); /* { dg-warning "writing 6 bytes into a region of size 5" } */
escape (b);
memset (&b->d, 0, offsetfrom (struct B, b, d) + 1); /* { dg-warning "writing 6 bytes into a region of size 5" } */
escape (b);
/* Same as above but clearing just elements of the second element
of the array. */
memset (&b[1].a.b, 0, offsetfrom (struct B, b[1], a.b) + 1); /* { dg-warning "writing 4 bytes into a region of size 3" } */
escape (b);
memset (&b[1].c, 0, offsetfrom (struct B, b[1], c) + 1); /* { dg-warning "writing 3 bytes into a region of size 2" } */
escape (b);
memset (&b[1].d, 0, offsetfrom (struct B, b[1], d) + 1); /* { dg-warning "writing 2 bytes into a region of size 1" } */
escape (b);
}
/* Verify that writing past the end of a dynamically allocated array
of known size is diagnosed. */
void test_memop_warn_alloc (const void *src)
{
size_t n;
n = range (8, 32);
struct A *a = __builtin_malloc (sizeof *a * 2);
memcpy (a, src, n); /* { dg-warning "writing between 8 and 32 bytes into a region of size 4 overflows the destination" "memcpy into allocated" { xfail *-*-*} } */
escape (a, src);
/* At -Wrawmem-overflow=1 the destination is considered to be
the whole array and its size is therefore sizeof a. */
memcpy (&a[0], src, n); /* { dg-warning "writing between 8 and 32 bytes into a region of size 4 overflows the destination" "memcpy into allocated" { xfail *-*-*} } */
escape (a, src);
/* Verify the same as above but by writing into the first mmeber
of the first element of the array. */
memcpy (&a[0].a, src, n); /* { dg-warning "writing between 8 and 32 bytes into a region of size 4 overflows the destination" "memcpy into allocated" { xfail *-*-*} } */
escape (a, src);
n = range (12, 32);
struct B *b = __builtin_malloc (sizeof *b * 2);
memcpy (&b[0], src, n); /* { dg-warning "writing between 12 and 32 bytes into a region of size 8 overflows the destination" "memcpy into allocated" { xfail *-*-*} } */
escape (b);
/* The following idiom of clearing multiple members of a struct is
used in a few places in the Linux kernel. Verify that a warning
is issued for it when it writes past the end of the array object. */
memset (&b[0].a.b, 0, offsetfrom (struct B, b, a.b) + 1); /* { dg-warning "writing 8 bytes into a region of size 7" "memcpy into allocated" { xfail *-*-*} } */
escape (b);
memset (&b->a.b, 0, offsetfrom (struct B, b, a.b) + 1); /* { dg-warning "writing 8 bytes into a region of size 7" "memcpy into allocated" { xfail *-*-*} } */
escape (b);
memset (&b[0].c, 0, offsetfrom (struct B, b, c) + 1); /* { dg-warning "writing 7 bytes into a region of size 6" "memcpy into allocated" { xfail *-*-*} } */
escape (b);
memset (&b->c, 0, offsetfrom (struct B, b, c) + 1); /* { dg-warning "writing 7 bytes into a region of size 6" "memcpy into allocated" { xfail *-*-*} } */
escape (b);
memset (&b[0].d, 0, offsetfrom (struct B, b, d) + 1); /* { dg-warning "writing 6 bytes into a region of size 5" "memcpy into allocated" { xfail *-*-*} } */
escape (b);
memset (&b->d, 0, offsetfrom (struct B, b, d) + 1); /* { dg-warning "writing 6 bytes into a region of size 5" "memcpy into allocated" { xfail *-*-*} } */
escape (b);
/* Same as above but clearing just elements of the second element
of the array. */
memset (&b[1].a.b, 0, offsetfrom (struct B, b[1], a.b) + 1); /* { dg-warning "writing 4 bytes into a region of size 3" "memcpy into allocated" { xfail *-*-*} } */
escape (b);
memset (&b[1].c, 0, offsetfrom (struct B, b[1], c) + 1); /* { dg-warning "writing 3 bytes into a region of size 2" "memcpy into allocated" { xfail *-*-*} } */
escape (b);
memset (&b[1].d, 0, offsetfrom (struct B, b[1], d) + 1); /* { dg-warning "writing 2 bytes into a region of size 1" "memcpy into allocated" { xfail *-*-*} } */
escape (b);
}
void test_memop_nowarn (const void *src)
{
struct B b[2];
size_t n = range (sizeof b, 32);
/* Verify that clearing the whole array is not diagnosed regardless
of whether the expression pointing to its beginning is obtained
from the array itself or its first member(s). */
memcpy (b, src, n);
escape (b);
memcpy (&b[0], src, n);
escape (b);
memcpy (&b[0].a, src, n);
escape (b, src);
memcpy (&b[0].a.a, src, n);
escape (b, src);
/* Clearing multiple elements of an array of structs. */
memset (&b[0].a.b, 0, sizeof b - offsetof (struct B, a.b));
escape (b);
memset (&b->a.b, 0, sizeof b - offsetof (struct B, a.b));
escape (b);
memset (&b[0].c, 0, sizeof b - offsetof (struct B, c));
escape (b);
memset (&b->c, 0, sizeof b - offsetof (struct B, c));
escape (b);
memset (&b[0].d, 0, sizeof b - offsetof (struct B, d));
escape (b);
memset (&b->d, 0, sizeof b - offsetof (struct B, d));
escape (b);
/* Same as above but clearing just elements of the second element
of the array. */
memset (&b[1].a.b, 0, sizeof b[1] - offsetof (struct B, a.b));
escape (b);
memset (&b[1].c, 0, sizeof b[1] - offsetof (struct B, c));
escape (b);
memset (&b[1].d, 0, sizeof b[1] - offsetof (struct B, d));
escape (b);
}
/* The foollowing function could specify in its API that it takes
an array of exactly two elements, as shown below. Verify that
writing into both elements is not diagnosed. */
void test_memop_nowarn_arg (struct A[2], const void*);
void test_memop_nowarn_arg (struct A *a, const void *src)
{
memcpy (a, src, 2 * sizeof *a);
escape (a, src);
memcpy (a, src, range (2 * sizeof *a, 123));
escape (a, src);
}
struct C { char a[3], b; };
struct D { struct C c; char d, e; };
extern char* strncpy (char*, const char*, __SIZE_TYPE__);
void test_stringop_warn (void)
{
size_t n = range (2 * sizeof (struct D) + 1, 33);
struct C c[2];
/* Similarly, at -Wstringop-overflow=1 the destination is considered
to be the whole array and its size is therefore sizeof c. */
strncpy (c[0].a, "123", n); /* { dg-warning "writing between 13 and 33 bytes into a region of size 8 overflows the destination" } */
escape (c);
}
void test_stringop_nowarn (void)
{
struct D d[2];
strncpy (d[0].c.a, "123", range (sizeof d, 32));
escape (d);
}
/* Test exercising -Wrawmem-overflow and -Wstringop-overflow warnings. */
/* { dg-do compile } */
/* { dg-options "-O2 -Wstringop-overflow=2" } */
#define offsetof(type, mem) __builtin_offsetof (type, mem)
/* Return the number of bytes from member MEM of TYPE to the end
of object OBJ. */
#define offsetfrom(type, obj, mem) (sizeof (obj) - offsetof (type, mem))
typedef __SIZE_TYPE__ size_t;
extern void* memcpy (void*, const void*, size_t);
extern void* memset (void*, int, __SIZE_TYPE__);
struct A { char a, b; };
struct B { struct A a; char c, d; };
/* Function to call to "escape" pointers from tests below to prevent
GCC from assuming the values of the objects they point to stay
the unchanged. */
void escape (void*, ...);
/* Function to "generate" a random number each time it's called. Declared
(but not defined) and used to prevent GCC from making assumptions about
their values based on the variables uses in the tested expressions. */
size_t random_unsigned_value (void);
/* Return a random unsigned value between MIN and MAX. */
static inline size_t
range (size_t min, size_t max)
{
const size_t val = random_unsigned_value ();
return val < min || max < val ? min : val;
}
void test_memop_warn_object (const void *src)
{
unsigned n = range (17, 29);
struct A a[2];
/* At both -Wstringop-overflow=2, like at 1, the destination of functions
that operate on raw memory is considered to be the whole array and its
size is therefore sizeof a. */
memcpy (&a[0], src, n); /* { dg-warning "writing between 17 and 29 bytes into a region of size 4 overflows the destination" } */
escape (a);
}
void test_memop_warn_subobject (const void *src)
{
unsigned n = range (17, 31);
struct B b[2];
/* At -Wrawmem-overflow=2 the destination is considered to be
the member sobobject of the first array element and its size
is therefore sizeof b[0].a. */
memcpy (&b[0].a, src, n); /* { dg-warning "writing between 17 and 31 bytes into a region of size 8 overflows the destination" } */
escape (b);
}
void test_memop_nowarn_subobject (void)
{
struct B b[2];
/* The following idiom of clearing multiple members of a struct
has been seen in a few places in the Linux kernel. Verify
that a warning is not issued for it. */
memset (&b[0].c, 0, sizeof b[0] - offsetof (struct B, c));
escape (b);
}
struct C { char a[3], b; };
struct D { struct C c; char d, e; };
extern char* strncpy (char*, const char*, __SIZE_TYPE__);
void test_stringop_warn_object (const char *str)
{
unsigned n = range (2 * sizeof (struct D), 32);
struct C c[2];
/* Similarly, at -Wstringop-overflow=2 the destination is considered
to be the array member of the first element of the array c and its
size is therefore sizeof c[0].a. */
strncpy (c[0].a, "123", n); /* { dg-warning "writing between 12 and 32 bytes into a region of size 3 overflows the destination" } */
escape (c);
strncpy (c[0].a, str, n); /* { dg-warning "writing between 12 and 32 bytes into a region of size 3 overflows the destination" } */
escape (c);
}
void test_stringop_warn_subobject (const char *src)
{
unsigned n = range (2 * sizeof (struct D), 32);
struct D d[2];
/* Same as above. */
strncpy (d[0].c.a, "123", n); /* { dg-warning "writing between 12 and 32 bytes into a region of size 3 overflows the destination" } */
escape (d);
strncpy (d[0].c.a, src, n); /* { dg-warning "writing between 12 and 32 bytes into a region of size 3 overflows the destination" } */
escape (d);
}
......@@ -24,15 +24,15 @@ test (int arg, ...)
*p = 0;
strncat (p, "abcdefghi", 10);
*p = 0;
strncat (p, "abcdefghij", 10); /* { dg-warning "will always overflow" } */
strncat (p, "abcdefghij", 10); /* { dg-warning "writing 11 bytes into a region of size 10 overflows the destination" } */
*p = 0;
strncat (p, "abcdefgh", 11);
*p = 0;
strncat (p, "abcdefghijkl", 11); /* { dg-warning "will always overflow" } */
strncat (p, "abcdefghijkl", 11); /* { dg-warning "specified bound 11 exceeds the size 10 of the destination" } */
*p = 0;
strncat (p, q, 9);
*p = 0;
strncat (p, q, 10); /* { dg-warning "might overflow" } */
strncat (p, q, 10); /* { dg-warning "specified bound 10 equals the size of the destination" } */
*p = 0;
strncat (p, q, 11); /* { dg-warning "might overflow" } */
strncat (p, q, 11); /* { dg-warning "specified bound 11 exceeds the size 10 of the destination" } */
}
......@@ -106,7 +106,7 @@ int
foo8 ()
{
char base[100];
memcpy ((void *)base, (const void *)pg0, 105);
memcpy ((void *)base, (const void *)pg0, 105); /* { dg-warning "writing 105 bytes into a region of size 100" } */
return (int)(base[32]);
}
......
......@@ -7,7 +7,7 @@ typedef __SIZE_TYPE__ size_t;
extern inline __attribute__((gnu_inline, always_inline, artificial)) void *
memcpy (void *__restrict dest, const void *__restrict src, size_t len)
{
return __builtin___memcpy_chk (dest, /* { dg-warning "will always overflow destination buffer" } */
return __builtin___memcpy_chk (dest, /* { dg-warning "writing" } */
src, len, __builtin_object_size (dest, 0));
}
......
......@@ -20,5 +20,5 @@ main (void)
return 0;
}
/* { dg-warning "will always overflow destination buffer" "" { target *-*-* } 10 } */
/* { dg-warning "writing" "" { target *-*-* } 10 } */
/* { dg-message "file included" "In file included" { target *-*-* } 0 } */
......@@ -12,5 +12,5 @@ main (void)
return 0;
}
/* { dg-warning "will always overflow destination buffer" "" { target *-*-* } 10 } */
/* { dg-warning "writing" "" { target *-*-* } 10 } */
/* { dg-message "file included" "In file included" { target *-*-* } 0 } */
......@@ -13,5 +13,5 @@ main (void)
return 0;
}
/* { dg-warning "will always overflow destination buffer" "" { target *-*-* } 10 } */
/* { dg-warning "writing" "" { target *-*-* } 10 } */
/* { dg-message "file included" "In file included" { target *-*-* } 0 } */
......@@ -710,4 +710,4 @@ f4 (char *x, char **y, int z, char w[64])
return z;
}
/* { dg-prune-output "\[\n\r\]*will always overflow\[\n\r\]*" } */
/* { dg-prune-output "\[\n\r\]*writing\[\n\r\]*" } */
/* { dg-do compile } */
/* { dg-additional-options "-Wno-stringop-overflow" } */
/* The loop below writes past the end of the global object a.
When the loop is transformed into a call to memcpy the buffer
overflow is detected and diagnosed by the -Wstringop-overflow
option enabled by default. */
typedef unsigned size_t;
struct {
......
/* { dg-do compile } */
/* { dg-options "-std=c99 -Wformat -Wformat-length=1 -ftrack-macro-expansion=0" } */
/* { dg-options "-Wformat -Wformat-length=1 -ftrack-macro-expansion=0" } */
/* { dg-require-effective-target int32plus } */
/* When debugging, define LINE to the line number of the test case to exercise
......@@ -1456,9 +1456,7 @@ void test_vsprintf_chk_int (__builtin_va_list va)
void test_snprintf_c_const (char *d)
{
T (-1, "%c", 0); /* { dg-warning "specified destination size \[0-9\]+ is too large" } */
__builtin_snprintf (d, INT_MAX, "%c", 0); /* { dg-warning "specified destination size 2147483647 is too large" "ilp32" { target { ilp32 } } } */
T (-1, "%c", 0); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
/* Verify the full text of the diagnostic for just the distinct messages
and use abbreviations in subsequent test cases. */
......@@ -1506,9 +1504,9 @@ void test_snprintf_chk_c_const (void)
/* Verify that specifying a size of the destination buffer that's
bigger than its actual size (normally determined and passed to
the function by __builtin_object_size) is diagnosed. */
__builtin___snprintf_chk (buffer, 3, 0, 2, " "); /* { dg-warning "always overflow|specified size 3 exceeds the size 2 of the destination" } */
__builtin___snprintf_chk (buffer, 3, 0, 2, " "); /* { dg-warning "specified bound 3 exceeds the size 2 of the destination" } */
T (-1, "%c", 0); /* { dg-warning "specified destination size \[^ \]* is too large" } */
T (-1, "%c", 0); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
T (0, "%c", 0);
T (0, "%c%c", 0, 0);
......@@ -1619,7 +1617,7 @@ void test_vsprintf_int (__builtin_va_list va)
void test_vsnprintf_s (__builtin_va_list va)
{
T (-1, "%s"); /* { dg-warning "specified destination size \[^ \]* is too large" } */
T (-1, "%s"); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
T (0, "%s");
T (1, "%s");
......@@ -1642,9 +1640,9 @@ void test_vsnprintf_chk_s (__builtin_va_list va)
/* Verify that specifying a size of the destination buffer that's
bigger than its actual size (normally determined and passed to
the function by __builtin_object_size) is diagnosed. */
__builtin___vsnprintf_chk (buffer, 123, 0, 122, "%-s", va); /* { dg-warning "always overflow|specified size 123 exceeds the size 122 of the destination object" } */
__builtin___vsnprintf_chk (buffer, 123, 0, 122, "%-s", va); /* { dg-warning "specified bound 123 exceeds the size 122 of the destination" } */
__builtin___vsnprintf_chk (buffer, __SIZE_MAX__, 0, 2, "%-s", va); /* { dg-warning "always overflow|destination size .\[0-9\]+. is too large" } */
__builtin___vsnprintf_chk (buffer, __SIZE_MAX__, 0, 2, "%-s", va); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
T (0, "%s");
T (1, "%s");
......
/* { dg-do compile } */
/* { dg-options "-std=c99 -O2 -Wformat -Wformat-length=1 -ftrack-macro-expansion=0" } */
/* { dg-options "-O2 -Wformat -Wformat-length=1 -ftrack-macro-expansion=0" } */
typedef __SIZE_TYPE__ size_t;
......@@ -248,34 +248,34 @@ 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); /* { dg-warning "specified destination size \[0-9\]+ is too large" "INT_MAX" { target ilp32 } } */
__builtin_snprintf (d, imax_p1, "%c", x); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." "INT_MAX + 1" { target lp64 } } */
/* { dg-warning "specified destination size \[0-9\]+ is too large" "" { target { ilp32 } } .-1 } */
__builtin_snprintf (d, imax, "%c", x);
__builtin_snprintf (d, imax_p1, "%c", x); /* { dg-warning "specified bound \[0-9\]+ exceeds .INT_MAX." "INT_MAX + 1" { target lp64 } } */
/* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" "INT_MAX + 1" { target { ilp32 } } .-1 } */
__builtin_vsnprintf (d, imax, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ is too large" "INT_MAX" { target ilp32 } } */
__builtin_vsnprintf (d, imax_p1, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." "INT_MAX + 1" { 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 bound \[0-9\]+ exceeds .INT_MAX." "INT_MAX + 1" { target lp64 } } */
/* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" "INT_MAX + 1" { target { ilp32 } } .-1 } */
__builtin___snprintf_chk (d, imax, 0, imax, "%c", x); /* { dg-warning "specified destination size \[0-9\]+ is too large" "INT_MAX" { target ilp32 } } */
__builtin___snprintf_chk (d, imax_p1, 0, imax_p1, "%c", x); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." "INT_MAX + 1" { target lp64 } } */
/* { dg-warning "specified destination size \[0-9\]+ is too large" "INT_MAX + 1" { 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 bound \[0-9\]+ exceeds .INT_MAX." "INT_MAX + 1" { target lp64 } } */
/* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" "INT_MAX + 1" { target { ilp32 } } .-1 } */
__builtin___vsnprintf_chk (d, imax, 0, imax, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ is too large" "INT_MAX" { target ilp32 } } */
__builtin___vsnprintf_chk (d, imax_p1, 0, imax_p1, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." "INT_MAX + 1" { 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 bound \[0-9\]+ exceeds .INT_MAX." "INT_MAX + 1" { target lp64 } } */
/* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" "INT_MAX + 1" { 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." "PTRDIFF_MAX - 1" { target lp64 } } */
__builtin_snprintf (d, ptrmax, " %c", x); /* { dg-warning "specified destination size \[0-9\]+ is too large" } */
__builtin_snprintf (d, ptrmax_m1, "%c", x); /* { dg-warning "specified bound \[0-9\]+ exceeds .INT_MAX." "PTRDIFF_MAX - 1" { target lp64 } } */
__builtin_snprintf (d, ptrmax, " %c", x); /* { dg-warning "specified bound \[0-9\]+ exceeds .INT_MAX." "PTRDIFF_MAX" { target lp64 } } */
__builtin_vsnprintf (d, ptrmax_m1, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." "PTRDIFF_MAX - 1" { target lp64 } } */
__builtin_vsnprintf (d, ptrmax, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ is too large" } */
__builtin_vsnprintf (d, ptrmax_m1, "%c", va); /* { dg-warning "specified bound \[0-9\]+ exceeds .INT_MAX." "PTRDIFF_MAX - 1" { target lp64 } } */
__builtin_vsnprintf (d, ptrmax, "%c", va); /* { dg-warning "specified bound \[0-9\]+ exceeds .INT_MAX." "PTRDIFF_MAX" { target lp64 } } */
__builtin___snprintf_chk (d, ptrmax_m1, 0, ptrmax_m1, "%c", x); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." "PTRDIFF_MAX - 1" { target lp64 } } */
__builtin___snprintf_chk (d, ptrmax, 0, ptrmax, "%c", x); /* { dg-warning "specified destination size \[0-9\]+ is too large" } */
__builtin___snprintf_chk (d, ptrmax_m1, 0, ptrmax_m1, "%c", x); /* { dg-warning "specified bound \[0-9\]+ exceeds .INT_MAX." "PTRDIFF_MAX - 1" { target lp64 } } */
__builtin___snprintf_chk (d, ptrmax, 0, ptrmax, "%c", x); /* { dg-warning "specified bound \[0-9\]+ exceeds .INT_MAX." "PTRDIFF_MAX" { target lp64 } } */
__builtin___vsnprintf_chk (d, ptrmax_m1, 0, ptrmax_m1, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ exceeds .INT_MAX." "PTRDIFF_MAX - 1" { target lp64 } } */
__builtin___vsnprintf_chk (d, ptrmax, 0, ptrmax, "%c", va); /* { dg-warning "specified destination size \[0-9\]+ is too large" } */
__builtin___vsnprintf_chk (d, ptrmax_m1, 0, ptrmax_m1, "%c", va); /* { dg-warning "specified bound \[0-9\]+ exceeds .INT_MAX." "PTRDIFF_MAX - 1" { target lp64 } } */
__builtin___vsnprintf_chk (d, ptrmax, 0, ptrmax, "%c", va); /* { dg-warning "specified bound \[0-9\]+ exceeds .INT_MAX." "PTRDIFF_MAX" { target lp64 } } */
}
......@@ -47,3 +47,6 @@
y(1) = 'hello world'
end subroutine
end
! Remove -Wstringop-overflow warnings.
! { dg-prune-output "overflows the destination" }
......@@ -9,7 +9,7 @@
ANER(1)='A '
ANER(2)=' '
LINE=' '
LINE(78:80)='xyz'
LINE(78:80)='xyz' ! { dg-warning "writing 3 bytes into a region of size 2" }
WRITE(*,'(A82)') "'"//LINE//"'"
END
......
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