Add -Wstringop-overread for reading past the end by string functions.

gcc/ChangeLog:

	* attribs.c (init_attr_rdwr_indices): Use global access_mode.
	* attribs.h (struct attr_access): Same.
	* builtins.c (fold_builtin_strlen): Add argument.
	(compute_objsize): Declare.
	(get_range): Declare.
	(check_read_access): New function.
	(access_ref::access_ref): Define ctor.
	(warn_string_no_nul): Add arguments.  Handle -Wstrintop-overread.
	(check_nul_terminated_array): Handle source strings of different
	ranges of sizes.
	(expand_builtin_strlen): Remove warning code, call check_read_access
	instead.  Declare locals closer to their initialization.
	(expand_builtin_strnlen): Same.
	(maybe_warn_for_bound): New function.
	(warn_for_access): Remove argument.  Handle -Wstrintop-overread.
	(inform_access): Change argument type.
	(get_size_range): New function.
	(check_access): Remove unused arguments.  Add new arguments.  Handle
	-Wstrintop-overread.  Move warning code to helpers and call them.
	Call check_nul_terminated_array.
	(check_memop_access): Remove unnecessary and provide additional
	arguments in calls.
	(expand_builtin_memchr): Call check_read_access.
	(expand_builtin_strcat): Remove unnecessary and provide additional
	arguments in calls.
	(expand_builtin_strcpy): Same.
	(expand_builtin_strcpy_args): Same.  Avoid testing no-warning bit.
	(expand_builtin_stpcpy_1): Remove unnecessary and provide additional
	arguments in calls.
	(expand_builtin_stpncpy): Same.
	(check_strncat_sizes): Same.
	(expand_builtin_strncat): Remove unnecessary and provide additional
	arguments in calls.  Adjust comments.
	(expand_builtin_strncpy): Remove unnecessary and provide additional
	arguments in calls.
	(expand_builtin_memcmp): Remove warning code.  Call check_access.
	(expand_builtin_strcmp): Call check_access instead of
	check_nul_terminated_array.
	(expand_builtin_strncmp): Handle -Wstrintop-overread.
	(expand_builtin_fork_or_exec): Call check_access instead of
	check_nul_terminated_array.
	(expand_builtin): Same.
	(fold_builtin_1): Pass additional argument.
	(fold_builtin_n): Same.
	(fold_builtin_strpbrk): Remove calls to check_nul_terminated_array.
	(expand_builtin_memory_chk): Add comments.
	(maybe_emit_chk_warning): Remove unnecessary and provide additional
	arguments in calls.
	(maybe_emit_sprintf_chk_warning): Same.  Adjust comments.
	* builtins.h (warn_string_no_nul): Add arguments.
	(struct access_ref): Add member and ctor argument.
	(struct access_data): Add members and ctor.
	(check_access): Adjust signature.
	* calls.c (maybe_warn_nonstring_arg): Return an indication of
	whether a warning was issued.  Issue -Wstrintop-overread instead
	of -Wstringop-overflow.
	(append_attrname): Adjust to naming changes.
	(maybe_warn_rdwr_sizes): Same.  Remove unnecessary and provide
	additional arguments in calls.
	* calls.h (maybe_warn_nonstring_arg): Return bool.
	* doc/invoke.texi (-Wstringop-overread): Document new option.
	* gimple-fold.c (gimple_fold_builtin_strcpy): Provide an additional
	argument in call.
	(gimple_fold_builtin_stpcpy): Same.
	* tree-ssa-uninit.c (maybe_warn_pass_by_reference): Adjust to naming
	changes.
	* tree.h (enum access_mode): New type.

gcc/c-family/ChangeLog:

	* c.opt (Wstringop-overread): New option.

gcc/testsuite/ChangeLog:

	* c-c++-common/Warray-bounds-7.c: Adjust expected warnings.
	* c-c++-common/Wrestrict.c: Remove xfail.
	* c-c++-common/attr-nonstring-3.c: Adjust text of expected warnings.
	* c-c++-common/attr-nonstring-6.c: Suppress -Wstringop-overread
	instead of -Wstringop-overflow.
	* c-c++-common/attr-nonstring-8.c: Adjust text of expected warnings.
	* g++.dg/torture/Wsizeof-pointer-memaccess1.C: Also suppress
	 -Wstringop-overread.
	* g++.dg/torture/Wsizeof-pointer-memaccess2.C: Same.
	* gcc.dg/Warray-bounds-39.c: Adjust expected warnings.
	* gcc.dg/Warray-bounds-40.c: Also suppress -Wstringop-overread.
	* gcc.dg/Warray-bounds-58.c: Remove xfail.  Also expect
	-Wstringop-overread.  Adjust text of expected warnings.
	* gcc.dg/Wsizeof-pointer-memaccess1.c: Also suppress
	 -Wstringop-overread.
	* gcc.dg/Wstringop-overflow-22.c: Adjust text of expected warnings.
	* gcc.dg/Wstringop-overflow-33.c: Expect -Wstringop-overread.
	* gcc.dg/Wstringop-overflow-9.c: Expect -Wstringop-overread.
	* gcc.dg/attr-nonstring-2.c: Adjust text of expected warnings.
	* gcc.dg/attr-nonstring-3.c: Same.
	* gcc.dg/attr-nonstring-4.c: Same.
	* gcc.dg/attr-nonstring.c: Expect -Wstringop-overread.
	* gcc.dg/builtin-stringop-chk-5.c: Adjust comment.
	* gcc.dg/builtin-stringop-chk-8.c: Enable -Wstringop-overread instead
	of -Wstringop-overflow.
	* gcc.dg/pr78902.c: Also expect -Wstringop-overread.
	* gcc.dg/pr79214.c: Adjust text of expected warnings.
	* gcc.dg/strcmpopt_10.c: Suppress valid -Wno-stringop-overread.
	* gcc.dg/strlenopt-57.c: Also expect -Wstringop-overread.
	* gcc.dg/torture/Wsizeof-pointer-memaccess1.c: Also suppress valid
	-Wno-stringop-overread.
	* gcc.dg/tree-ssa/builtins-folding-gimple-ub.c: Same.
	* gcc.dg/uninit-33.c: Same.
	* gcc.dg/warn-strnlen-no-nul-2.c: Adjust text of expected warning.
	* gcc.dg/warn-strnlen-no-nul.c: Same.
	* gcc.target/i386/strcmpopt_6.c: Suppress -Wstringop-overread.
	* gcc.dg/Wstringop-overread-2.c: New test.
	* gcc.dg/Wstringop-overread.c: New test.
This commit is contained in:
Martin Sebor 2020-08-28 13:13:28 -06:00
parent 26c24398d3
commit d14c547abd
43 changed files with 1791 additions and 674 deletions

View File

@ -2045,10 +2045,10 @@ init_attr_rdwr_indices (rdwr_map *rwm, tree fntype)
switch (*m)
{
case 'r': acc.mode = acc.read_only; break;
case 'w': acc.mode = acc.write_only; break;
case 'x': acc.mode = acc.read_write; break;
case '-': acc.mode = acc.none; break;
case 'r': acc.mode = access_read_only; break;
case 'w': acc.mode = access_write_only; break;
case 'x': acc.mode = access_read_write; break;
case '-': acc.mode = access_none; break;
default: gcc_unreachable ();
}

View File

@ -234,7 +234,6 @@ struct attr_access
unsigned sizarg;
/* The access mode. */
enum access_mode { none, read_only, write_only, read_write };
access_mode mode;
};

File diff suppressed because it is too large Load Diff

View File

@ -153,38 +153,56 @@ extern internal_fn associated_internal_fn (tree);
extern internal_fn replacement_internal_fn (gcall *);
extern bool check_nul_terminated_array (tree, tree, tree = NULL_TREE);
extern void warn_string_no_nul (location_t, const char *, tree, tree);
extern void warn_string_no_nul (location_t, tree, const char *, tree,
tree, tree = NULL_TREE, bool = false,
const wide_int[2] = NULL);
extern tree unterminated_array (tree, tree * = NULL, bool * = NULL);
extern bool builtin_with_linkage_p (tree);
/* Describes a reference to an object used in an access. */
struct access_ref
{
access_ref (): ref ()
{
/* Set to valid. */
offrng[0] = offrng[1] = 0;
/* Invalidate. */
sizrng[0] = sizrng[1] = -1;
}
/* Set the bounds of the reference to at most as many bytes
as the first argument or unknown when null, and at least
one when the second argument is true unless the first one
is a constant zero. */
access_ref (tree = NULL_TREE, bool = false);
/* Reference to the object. */
/* Reference to the accessed object(s). */
tree ref;
/* Range of offsets into and sizes of the object(s). */
/* Range of byte offsets into and sizes of the object(s). */
offset_int offrng[2];
offset_int sizrng[2];
/* Range of the bound of the access: denotes that the access
is at least BNDRNG[0] bytes but no more than BNDRNG[1].
For string functions the size of the actual access is
further constrained by the length of the string. */
offset_int bndrng[2];
};
/* Describes a pair of references used in an access by built-in
functions like memcpy. */
struct access_data
{
/* Set the access to at most MAXWRITE and MAXREAD bytes, and
at least 1 when MINWRITE or MINREAD, respectively, is set. */
access_data (tree expr, access_mode mode,
tree maxwrite = NULL_TREE, bool minwrite = false,
tree maxread = NULL_TREE, bool minread = false)
: call (expr),
dst (maxwrite, minwrite), src (maxread, minread), mode (mode) { }
/* Built-in function call. */
tree call;
/* Destination and source of the access. */
access_ref dst, src;
/* Read-only for functions like memcmp or strlen, write-only
for memset, read-write for memcpy or strcat. */
access_mode mode;
};
extern bool check_access (tree, tree, tree, tree, tree, tree, tree,
bool = true, const access_data * = NULL);
extern bool check_access (tree, tree, tree, tree, tree,
access_mode, const access_data * = NULL);
#endif /* GCC_BUILTINS_H */

View File

@ -823,6 +823,10 @@ C ObjC C++ LTO ObjC++ Joined RejectNegative UInteger Var(warn_stringop_overflow)
Under the control of Object Size type, warn about buffer overflow in string
manipulation functions like memcpy and strcpy.
Wstringop-overread
C ObjC C++ LTO ObjC++ Var(warn_stringop_overread) Init(1) Warning LangEnabledBy(C ObjC C++ LTO ObjC++, Wall)
Warn about reading past the end of a source array in string manipulation functions like memchr and memcpy.
Wstringop-truncation
C ObjC C++ LTO ObjC++ Var(warn_stringop_truncation) Warning Init (1) LangEnabledBy(C ObjC C++ LTO ObjC++, Wall)
Warn about truncation in string manipulation functions like strncat and strncpy.

View File

@ -1274,7 +1274,7 @@ get_size_range (tree exp, tree range[2], bool allow_zero /* = false */)
if (range_type == VR_VARYING)
{
if (integral)
{
{
/* Use the full range of the type of the expression when
no value range information is available. */
range[0] = TYPE_MIN_VALUE (exptype);
@ -1559,22 +1559,23 @@ get_attr_nonstring_decl (tree expr, tree *ref)
return NULL_TREE;
}
/* Warn about passing a non-string array/pointer to a function that
expects a nul-terminated string argument. */
/* Warn about passing a non-string array/pointer to a built-in function
that expects a nul-terminated string argument. Returns true if
a warning has been issued.*/
void
bool
maybe_warn_nonstring_arg (tree fndecl, tree exp)
{
if (!fndecl || !fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
return;
return false;
if (TREE_NO_WARNING (exp) || !warn_stringop_overflow)
return;
if (TREE_NO_WARNING (exp) || !warn_stringop_overread)
return false;
/* Avoid clearly invalid calls (more checking done below). */
unsigned nargs = call_expr_nargs (exp);
if (!nargs)
return;
return false;
/* The bound argument to a bounded string function like strncpy. */
tree bound = NULL_TREE;
@ -1666,22 +1667,27 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
if (bndrng[0])
{
/* Diagnose excessive bound prior the adjustment below and
/* Diagnose excessive bound prior to the adjustment below and
regardless of attribute nonstring. */
tree maxobjsize = max_object_size ();
if (tree_int_cst_lt (maxobjsize, bndrng[0]))
{
bool warned = false;
if (tree_int_cst_equal (bndrng[0], bndrng[1]))
warning_at (loc, OPT_Wstringop_overflow_,
"%K%qD specified bound %E "
"exceeds maximum object size %E",
exp, fndecl, bndrng[0], maxobjsize);
warned = warning_at (loc, OPT_Wstringop_overread,
"%K%qD specified bound %E "
"exceeds maximum object size %E",
exp, fndecl, bndrng[0], maxobjsize);
else
warning_at (loc, OPT_Wstringop_overflow_,
"%K%qD specified bound [%E, %E] "
"exceeds maximum object size %E",
exp, fndecl, bndrng[0], bndrng[1], maxobjsize);
return;
warned = warning_at (loc, OPT_Wstringop_overread,
"%K%qD specified bound [%E, %E] "
"exceeds maximum object size %E",
exp, fndecl, bndrng[0], bndrng[1],
maxobjsize);
if (warned)
TREE_NO_WARNING (exp) = true;
return warned;
}
}
@ -1710,6 +1716,7 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
}
}
bool any_arg_warned = false;
/* Iterate over the built-in function's formal arguments and check
each const char* against the actual argument. If the actual
argument is declared attribute non-string issue a warning unless
@ -1820,19 +1827,19 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
if (wi::ltu_p (asize, wibnd))
{
if (bndrng[0] == bndrng[1])
warned = warning_at (loc, OPT_Wstringop_overflow_,
warned = warning_at (loc, OPT_Wstringop_overread,
"%qD argument %i declared attribute "
"%<nonstring%> is smaller than the specified "
"bound %wu",
fndecl, argno + 1, wibnd.to_uhwi ());
else if (wi::ltu_p (asize, wi::to_offset (bndrng[0])))
warned = warning_at (loc, OPT_Wstringop_overflow_,
warned = warning_at (loc, OPT_Wstringop_overread,
"%qD argument %i declared attribute "
"%<nonstring%> is smaller than "
"the specified bound [%E, %E]",
fndecl, argno + 1, bndrng[0], bndrng[1]);
else
warned = warning_at (loc, OPT_Wstringop_overflow_,
warned = warning_at (loc, OPT_Wstringop_overread,
"%qD argument %i declared attribute "
"%<nonstring%> may be smaller than "
"the specified bound [%E, %E]",
@ -1842,14 +1849,22 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
; /* Avoid warning for calls to strncat() when the bound
is equal to the size of the non-string argument. */
else if (!bound)
warned = warning_at (loc, OPT_Wstringop_overflow_,
warned = warning_at (loc, OPT_Wstringop_overread,
"%qD argument %i declared attribute %<nonstring%>",
fndecl, argno + 1);
if (warned)
inform (DECL_SOURCE_LOCATION (decl),
"argument %qD declared here", decl);
{
inform (DECL_SOURCE_LOCATION (decl),
"argument %qD declared here", decl);
any_arg_warned = true;
}
}
if (any_arg_warned)
TREE_NO_WARNING (exp) = true;
return any_arg_warned;
}
/* Issue an error if CALL_EXPR was flagged as requiring
@ -1896,11 +1911,11 @@ append_attrname (const std::pair<int, attr_access> &access,
size_t len = strlen (attrstr);
const char* const atname
= (access.second.mode == attr_access::read_only
= (access.second.mode == access_read_only
? "read_only"
: (access.second.mode == attr_access::write_only
: (access.second.mode == access_write_only
? "write_only"
: (access.second.mode == attr_access::read_write
: (access.second.mode == access_read_write
? "read_write" : "none")));
const char *sep = len ? ", " : "";
@ -2045,7 +2060,7 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
tree objsize = compute_objsize (ptr, 0);
tree srcsize;
if (access.second.mode == attr_access::write_only)
if (access.second.mode == access_write_only)
{
/* For a write-only argument there is no source. */
srcsize = NULL_TREE;
@ -2055,8 +2070,8 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
/* For read-only and read-write attributes also set the source
size. */
srcsize = objsize;
if (access.second.mode == attr_access::read_only
|| access.second.mode == attr_access::none)
if (access.second.mode == access_read_only
|| access.second.mode == access_none)
{
/* For a read-only attribute there is no destination so
clear OBJSIZE. This emits "reading N bytes" kind of
@ -2070,8 +2085,8 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
iteration so that accesses via different arguments are
diagnosed. */
TREE_NO_WARNING (exp) = false;
check_access (exp, NULL_TREE, NULL_TREE, size, /*maxread=*/ NULL_TREE,
srcsize, objsize, access.second.mode != attr_access::none);
check_access (exp, size, /*maxread=*/ NULL_TREE, srcsize, objsize,
access.second.mode);
if (TREE_NO_WARNING (exp))
/* If check_access issued a warning above, append the relevant

View File

@ -132,7 +132,7 @@ extern bool reference_callee_copied (CUMULATIVE_ARGS *,
const function_arg_info &);
extern void maybe_warn_alloc_args_overflow (tree, tree, tree[2], int[2]);
extern tree get_attr_nonstring_decl (tree, tree * = NULL);
extern void maybe_warn_nonstring_arg (tree, tree);
extern bool maybe_warn_nonstring_arg (tree, tree);
extern bool get_size_range (tree, tree[2], bool = false);
extern rtx rtx_for_static_chain (const_tree, bool);
extern bool cxx17_empty_base_field_p (const_tree);

View File

@ -366,7 +366,8 @@ Objective-C and Objective-C++ Dialects}.
-Wstack-protector -Wstack-usage=@var{byte-size} -Wstrict-aliasing @gol
-Wstrict-aliasing=n -Wstrict-overflow -Wstrict-overflow=@var{n} @gol
-Wstring-compare @gol
-Wstringop-overflow=@var{n} -Wno-stringop-truncation @gol
-Wno-stringop-overflow -Wno-stringop-overread @gol
-Wno-stringop-truncation @gol
-Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{|}malloc@r{]} @gol
-Wswitch -Wno-switch-bool -Wswitch-default -Wswitch-enum @gol
-Wno-switch-outside-range -Wno-switch-unreachable -Wsync-nand @gol
@ -6754,6 +6755,7 @@ void f (char *d)
@option{-Wstring-compare} is enabled by @option{-Wextra}.
@item -Wno-stringop-overflow
@item -Wstringop-overflow
@itemx -Wstringop-overflow=@var{type}
@opindex Wstringop-overflow
@ -6795,6 +6797,15 @@ const char* f (enum Color clr)
Option @option{-Wstringop-overflow=2} is enabled by default.
@item -Wno-stringop-overread
@opindex Wstringop-overread
@opindex Wno-stringop-overread
Warn for calls to string manipulation functions such as @code{memchr},
@code{strcpy} that are determined to read past the end of the source
sequence.
Option @option{-Wstringop-overread} is enabled by default.
@table @gcctabopt
@item -Wstringop-overflow
@itemx -Wstringop-overflow=1
@ -7502,8 +7513,12 @@ This warning is also enabled by @option{-Wshadow=local}.
Warn whenever an object is defined whose size exceeds @var{byte-size}.
@option{-Wlarger-than=}@samp{PTRDIFF_MAX} is enabled by default.
Warnings controlled by the option can be disabled either by specifying
@var{byte-size} of @samp{SIZE_MAX} or more or by
@option{-Wno-larger-than}.
@var{byte-size} of @samp{SIZE_MAX} or more or by @option{-Wno-larger-than}.
Also warn for calls to bounded functions such as @code{memchr} or
@code{strnlen} that specify a bound greater than the largest possible
object, which is @samp{PTRDIFF_MAX} bytes by default. These warnings
can only be disabled by @option{-Wno-larger-than}.
@item -Wno-larger-than
@opindex Wno-larger-than

View File

@ -1875,7 +1875,7 @@ gimple_fold_builtin_strcpy (gimple_stmt_iterator *gsi,
{
/* Avoid folding calls with unterminated arrays. */
if (!gimple_no_warning_p (stmt))
warn_string_no_nul (loc, "strcpy", src, nonstr);
warn_string_no_nul (loc, NULL_TREE, "strcpy", src, nonstr);
gimple_set_no_warning (stmt, true);
return false;
}
@ -3074,11 +3074,16 @@ gimple_fold_builtin_stpcpy (gimple_stmt_iterator *gsi)
/* Set to non-null if ARG refers to an unterminated array. */
c_strlen_data data = { };
/* The size of the unterminated array if SRC referes to one. */
tree size;
/* True if the size is exact/constant, false if it's the lower bound
of a range. */
bool exact;
tree len = c_strlen (src, 1, &data, 1);
if (!len
|| TREE_CODE (len) != INTEGER_CST)
{
data.decl = unterminated_array (src);
data.decl = unterminated_array (src, &size, &exact);
if (!data.decl)
return false;
}
@ -3087,7 +3092,8 @@ gimple_fold_builtin_stpcpy (gimple_stmt_iterator *gsi)
{
/* Avoid folding calls with unterminated arrays. */
if (!gimple_no_warning_p (stmt))
warn_string_no_nul (loc, "stpcpy", src, data.decl);
warn_string_no_nul (loc, NULL_TREE, "stpcpy", src, data.decl, size,
exact);
gimple_set_no_warning (stmt, true);
return false;
}

View File

@ -29,52 +29,52 @@ void sink (unsigned);
void test_zero_length_array (void)
{
T (a0.a); // { dg-warning "\\\[-Warray-bounds" }
T (a0.a - 1); // { dg-warning "\\\[-Warray-bounds" }
T (a0.a + 1); // { dg-warning "\\\[-Warray-bounds" }
T (a0.a + 9); // { dg-warning "\\\[-Warray-bounds" }
T (a0.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (a0.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (a0.a); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a0.a - 1); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a0.a + 1); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a0.a + 9); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a0.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a0.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a0.a + SIZE_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (a0_0.a); // { dg-warning "\\\[-Warray-bounds" }
T (a0_0.a - 1); // { dg-warning "\\\[-Warray-bounds" }
T (a0_0.a + 1); // { dg-warning "\\\[-Warray-bounds" }
T (a0_0.a + 9); // { dg-warning "\\\[-Warray-bounds" }
T (a0_0.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (a0_0.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (a0_0.a + 1); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a0_0.a + 9); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a0_0.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a0_0.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a0_0.a + SIZE_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (a0_0_.a); // { dg-warning "\\\[-Warray-bounds" }
T (a0_0_.a - 1); // { dg-warning "\\\[-Warray-bounds" }
T (a0_0_.a + 1); // { dg-warning "\\\[-Warray-bounds" }
T (a0_0_.a + 9); // { dg-warning "\\\[-Warray-bounds" }
T (a0_0_.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (a0_0_.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (a0_0_.a + 1); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a0_0_.a + 9); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a0_0_.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a0_0_.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a0_0_.a + SIZE_MAX); // { dg-warning "\\\[-Warray-bounds" }
}
void test_one_element_array (void)
{
T (a1.a - 1); // { dg-warning "\\\[-Warray-bounds" }
T (a1.a + 1); // { dg-warning "\\\[-Warray-bounds" }
T (a1.a + 9); // { dg-warning "\\\[-Warray-bounds" }
T (a1.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (a1.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (a1.a + 1); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a1.a + 9); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a1.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a1.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a1.a + SIZE_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (a1_0.a - 1); // { dg-warning "\\\[-Warray-bounds" }
T (a1_0.a + 1); // { dg-warning "\\\[-Warray-bounds" }
T (a1_0.a + 9); // { dg-warning "\\\[-Warray-bounds" }
T (a1_0.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (a1_0.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (a1_0.a + 1); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a1_0.a + 9); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a1_0.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a1_0.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a1_0.a + SIZE_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (a1_0_.a - 1); // { dg-warning "\\\[-Warray-bounds" }
T (a1_0_.a + 1); // { dg-warning "\\\[-Warray-bounds" }
T (a1_0_.a + 9); // { dg-warning "\\\[-Warray-bounds" }
T (a1_0_.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (a1_0_.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (a1_0_.a + 1); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a1_0_.a + 9); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a1_0_.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a1_0_.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (a1_0_.a + SIZE_MAX); // { dg-warning "\\\[-Warray-bounds" }
}
@ -82,26 +82,25 @@ void test_flexible_array_member (void)
{
T (ax.a); // { dg-warning "\\\[-Warray-bounds" }
T (ax.a - 1); // { dg-warning "\\\[-Warray-bounds" }
T (ax.a + 1); // { dg-warning "\\\[-Warray-bounds" }
T (ax.a + 9); // { dg-warning "\\\[-Warray-bounds" }
T (ax.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (ax.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (ax.a + 1); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (ax.a + 9); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (ax.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (ax.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (ax.a + SIZE_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (ax_0.a); // { dg-warning "\\\[-Warray-bounds" }
T (ax_0.a - 1); // { dg-warning "\\\[-Warray-bounds" }
T (ax_0.a + 1); // { dg-warning "\\\[-Warray-bounds" }
T (ax_0.a + 9); // { dg-warning "\\\[-Warray-bounds" }
T (ax_0.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (ax_0.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (ax_0.a + 1); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (ax_0.a + 9); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (ax_0.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (ax_0.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (ax_0.a + SIZE_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (ax_0_.a); // { dg-warning "\\\[-Warray-bounds" }
T (ax_0_.a - 1); // { dg-warning "\\\[-Warray-bounds" }
T (ax_0_.a + 1); // { dg-warning "\\\[-Warray-bounds" }
T (ax_0_.a + 9); // { dg-warning "\\\[-Warray-bounds" }
T (ax_0_.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (ax_0_.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds" }
T (ax_0_.a + 1); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (ax_0_.a + 9); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (ax_0_.a + INT_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (ax_0_.a + PTRDIFF_MAX); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
T (ax_0_.a + SIZE_MAX); // { dg-warning "\\\[-Warray-bounds" }
}

View File

@ -637,9 +637,7 @@ void test_strcpy_cst (ptrdiff_t i)
T ("012", a, a + 1); /* { dg-warning "accessing 3 bytes at offsets 0 and 1 overlaps 2 bytes at offset 1" "strcpy" } */
T ("012", a, a + 2);
T ("012", a, a + 3);
/* The following doesn't overlap but it should trigger -Wstringop-overflow
for reading past the end. */
T ("012", a, a + sizeof a); /* { dg-warning "\\\[-Wstringop-overflow" "pr81437" { xfail *-*-* } } */
T ("012", a, a + sizeof a); /* { dg-warning "\\\[-Wstringop-overread" "pr81437" } */
/* The terminating nul written to d[2] overwrites s[0]. */
T ("0123", a, a + 2); /* { dg-warning "accessing 3 bytes at offsets 0 and 2 overlaps 1 byte at offset 2" } */

View File

@ -379,9 +379,9 @@ void test_stnrdup_warn (struct MemArrays *p)
T (strndup (p->arr, N));
T (strndup (arr, N + 1)); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound 5" } */
T (strndup (arr, N + 1)); /* { dg-warning "specified bound 5 exceeds source size 4" } */
T (strndup (parr, N + 1));
T (strndup (p->arr, N + 1)); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound 5" } */
T (strndup (p->arr, N + 1)); /* { dg-warning "specified bound 5 exceeds source size 4" } */
T (strndup (p->parr, N + 1));
}

View File

@ -1,7 +1,7 @@
/* PR 85623 - strncmp() warns about attribute 'nonstring' incorrectly
in -Wstringop-overflow
{ dg-do compile }
{ dg-options "-O2 -Wstringop-overflow -ftrack-macro-expansion=0" } */
{ dg-options "-O2 -Wstringop-overread -ftrack-macro-expansion=0" } */
#include "../gcc.dg/range.h"
@ -41,15 +41,15 @@ void test_strcmp_cst (void)
T (strcmp (S (1), a3));
T (strcmp (S (2), a3));
/* The following reads a3[3]. */
T (strcmp (S (3), a3)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strcmp (S (3), a3)); /* { dg-warning "\\\[-Wstringop-overread" } */
/* The following also reads past the end of a3. */
T (strcmp (S (9), a3)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strcmp (S (9), a3)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strcmp (a3, S (0)));
T (strcmp (a3, S (1)));
T (strcmp (a3, S (2)));
T (strcmp (a3, S (3))); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strcmp (a3, S (9))); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strcmp (a3, S (3))); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strcmp (a3, S (9))); /* { dg-warning "\\\[-Wstringop-overread" } */
}
@ -62,16 +62,16 @@ void test_strcmp_range (const char *s)
T (strcmp (a3, s));
s = signed_value () < 0 ? S (0) : S (3);
T (strcmp (a3, s)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strcmp (a3, s)); /* { dg-warning "\\\[-Wstringop-overread" } */
s = signed_value () < 0 ? S (1) : S (2);
T (strcmp (a3, s));
s = signed_value () < 0 ? S (1) : S (3);
T (strcmp (a3, s)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strcmp (a3, s)); /* { dg-warning "\\\[-Wstringop-overread" } */
s = signed_value () < 0 ? S (3) : S (4);
T (strcmp (a3, s)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strcmp (a3, s)); /* { dg-warning "\\\[-Wstringop-overread" } */
}
@ -81,21 +81,21 @@ void test_strncmp_cst (void)
T (strncmp (S (1), a3, 2));
T (strncmp (S (2), a3, 3));
T (strncmp (S (3), a3, 3));
T (strncmp (S (3), a3, 4)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strncmp (S (3), a3, 4)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strncmp (S (9), a3, 3));
T (strncmp (S (9), a3, 4)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strncmp (S (9), a3, 5)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strncmp (S (9), a3, 4)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strncmp (S (9), a3, 5)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strncmp (a3, S (0), 1));
T (strncmp (a3, S (1), 2));
T (strncmp (a3, S (2), 3));
T (strncmp (a3, S (3), 3));
T (strncmp (a3, S (3), 4)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strncmp (a3, S (3), 4)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strncmp (a3, S (9), 3));
T (strncmp (a3, S (9), 4)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strncmp (a3, S (9), 5)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strncmp (a3, S (9), 4)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strncmp (a3, S (9), 5)); /* { dg-warning "\\\[-Wstringop-overread" } */
}
void test_strncmp_range (const char *s)
@ -110,8 +110,8 @@ void test_strncmp_range (const char *s)
T (strncmp (a3, S (5), UR (1, 4)));
T (strncmp (a3, S (5), UR (2, 5)));
T (strncmp (a3, S (5), UR (3, 6)));
T (strncmp (a3, S (5), UR (4, 7))); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strncmp (a3, S (5), UR (7, 9))); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strncmp (a3, S (5), UR (4, 7))); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strncmp (a3, S (5), UR (7, 9))); /* { dg-warning "\\\[-Wstringop-overread" } */
s = signed_value () < 0 ? S (0) : S (1);
T (strncmp (a3, s, UR (1, 3)));
@ -124,7 +124,7 @@ void test_strncmp_range (const char *s)
T (strncmp (a3, s, UR (1, 4)));
T (strncmp (a3, s, UR (2, 5)));
T (strncmp (a3, s, UR (3, 6)));
T (strncmp (a3, s, UR (4, 7))); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strncmp (a3, s, UR (4, 7))); /* { dg-warning "\\\[-Wstringop-overread" } */
}
void test_strncasecmp (void)
@ -133,21 +133,21 @@ void test_strncasecmp (void)
T (strncasecmp (S (1), a3, 2));
T (strncasecmp (S (2), a3, 3));
T (strncasecmp (S (3), a3, 3));
T (strncasecmp (S (3), a3, 4)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strncasecmp (S (3), a3, 4)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strncasecmp (S (9), a3, 3));
T (strncasecmp (S (9), a3, 4)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strncasecmp (S (9), a3, 5)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strncasecmp (S (9), a3, 4)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strncasecmp (S (9), a3, 5)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strncasecmp (a3, S (0), 1));
T (strncasecmp (a3, S (1), 2));
T (strncasecmp (a3, S (2), 3));
T (strncasecmp (a3, S (3), 3));
T (strncasecmp (a3, S (3), 4)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strncasecmp (a3, S (3), 4)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strncasecmp (a3, S (9), 3));
T (strncasecmp (a3, S (9), 4)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strncasecmp (a3, S (9), 5)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strncasecmp (a3, S (9), 4)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strncasecmp (a3, S (9), 5)); /* { dg-warning "\\\[-Wstringop-overread" } */
}
void test_strspn (void)
@ -155,31 +155,31 @@ void test_strspn (void)
/* strspn must traverse all characters in the second argument except
when the first string is empty. */
T (strspn (S (0), a3));
T (strspn (S (1), a3)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strspn (S (2), a3)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strspn (S (3), a3)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strspn (S (9), a3)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strspn (S (1), a3)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strspn (S (2), a3)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strspn (S (3), a3)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strspn (S (9), a3)); /* { dg-warning "\\\[-Wstringop-overread" } */
/* Similarly, strspn must traverse all characters in the first argument
except when the second string is empty. */
T (strspn (a3, S (0)));
T (strspn (a3, S (1))); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strspn (a3, S (2))); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strspn (a3, S (3))); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strspn (a3, S (9))); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strspn (a3, S (1))); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strspn (a3, S (2))); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strspn (a3, S (3))); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strspn (a3, S (9))); /* { dg-warning "\\\[-Wstringop-overread" } */
}
void test_strcspn (void)
{
T (strcspn (S (0), a3));
T (strcspn (S (1), a3)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strcspn (S (2), a3)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strcspn (S (3), a3)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strcspn (S (9), a3)); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strcspn (S (1), a3)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strcspn (S (2), a3)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strcspn (S (3), a3)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strcspn (S (9), a3)); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strcspn (a3, S (0))); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strcspn (a3, S (1))); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strcspn (a3, S (2))); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strcspn (a3, S (3))); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strcspn (a3, S (9))); /* { dg-warning "\\\[-Wstringop-overflow" } */
T (strcspn (a3, S (0))); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strcspn (a3, S (1))); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strcspn (a3, S (2))); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strcspn (a3, S (3))); /* { dg-warning "\\\[-Wstringop-overread" } */
T (strcspn (a3, S (9))); /* { dg-warning "\\\[-Wstringop-overread" } */
}

View File

@ -85,7 +85,7 @@ void test_strncat_nonstring_var (char *d, size_t n)
T (strncat (nd3, ns5, UR (1, 2)));
T (strncat (nd3, ns5, UR (2, 3)));
T (strncat (nd3, ns5, UR (3, 4)));
T (strncat (nd3, ns5, UR (4, 5))); /* { dg-warning "specified bound between 4 and 5 exceeds destination size 3" } */
T (strncat (nd3, ns5, UR (4, 5))); /* { dg-warning "specified bound \\\[4, 5] exceeds destination size 3" } */
T (strncat (nd5, ns3, UR (0, 1)));
T (strncat (nd5, ns3, UR (1, 2)));

View File

@ -1,6 +1,6 @@
// Test -Wsizeof-pointer-memaccess warnings.
// { dg-do compile }
// { dg-options "-Wall -Wno-array-bounds -Wno-sizeof-array-argument -Wno-stringop-overflow -Wno-stringop-truncation" }
// { dg-options "-Wall -Wno-array-bounds -Wno-sizeof-array-argument -Wno-stringop-overflow -Wno-stringop-overread -Wno-stringop-truncation" }
// Test just twice, once with -O0 non-fortified, once with -O2 fortified.
// { dg-skip-if "" { *-*-* } { "*" } { "-O0" "-O2" } }
// { dg-skip-if "" { *-*-* } { "-flto" } { "" } }

View File

@ -1,6 +1,6 @@
// Test -Wsizeof-pointer-memaccess warnings.
// { dg-do compile }
// { dg-options "-Wall -Wno-array-bounds -Wno-sizeof-array-argument -Wno-stringop-overflow -Wno-stringop-truncation" }
// { dg-options "-Wall -Wno-array-bounds -Wno-sizeof-array-argument -Wno-stringop-overflow -Wno-stringop-overread -Wno-stringop-truncation" }
// Test just twice, once with -O0 non-fortified, once with -O2 fortified,
// suppressing buffer overflow warnings.
// { dg-skip-if "" { *-*-* } { "*" } { "-O0" "-O2" } }

View File

@ -21,65 +21,65 @@ char d[4];
void* test_memcpy_s0_1 (void *d)
{
return memcpy (d, s0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return memcpy (d, s0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
void* test_memcpy_s0_2 (void *d)
{
return memcpy (d, s0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return memcpy (d, s0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
void* test_memcpy_s0_0_1 (void *d)
{
return memcpy (d, s0_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return memcpy (d, s0_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
void* test_memcpy_s0_0_2 (void *d)
{
return memcpy (d, s0_0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return memcpy (d, s0_0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
void* test_memcpy_s0_1_1 (void *d)
{
return memcpy (d, s0_1, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return memcpy (d, s0_1, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
void* test_memcpy_s0_1_2 (void *d)
{
return memcpy (d, s0_1, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return memcpy (d, s0_1, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
void* test_memcpy_s1_0_1 (void *d)
{
return memcpy (d, s1_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return memcpy (d, s1_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
void* test_memcpy_s1_0_2 (void *d)
{
return memcpy (d, s1_0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return memcpy (d, s1_0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
void* test_memmove_s0_1 (void *d)
{
return memmove (d, s0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return memmove (d, s0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
void* test_memmove_s0_2 (void *d)
{
return memmove (d, s0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return memmove (d, s0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
void* test_memmove_s0_0_1 (void *d)
{
return memmove (d, s0_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return memmove (d, s0_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
void* test_memmove_s0_0_2 (void *d)
{
return memmove (d, s0_0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return memmove (d, s0_0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
@ -92,57 +92,57 @@ const struct Empty e1_0[1][0] = { };
void* test_memcpy_e_1 (void *d)
{
return memcpy (d, &e, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return memcpy (d, &e, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
void* test_memcpy_e0_1 (void *d)
{
return memcpy (d, e0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return memcpy (d, e0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
void* test_memcpy_e0_0_1 (void *d)
{
return memcpy (d, e0_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return memcpy (d, e0_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
void* test_memcpy_e0_1_1 (void *d)
{
return memcpy (d, e0_1, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return memcpy (d, e0_1, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
void* test_memcpy_e1_0_1 (void *d)
{
return memcpy (d, e1_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return memcpy (d, e1_0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
char* test_strcpy_s0 (char *d)
{
return strcpy (d, s0); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return strcpy (d, s0); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
char* test_strcpy_s0_0 (char *d)
{
return strcpy (d, s0_0[0]); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return strcpy (d, s0_0[0]); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
char* test_strncpy_s0_1 (char *d)
{
return strncpy (d, s0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return strncpy (d, s0, 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
char* test_strncpy_s0_2 (char *d)
{
return strncpy (d, s0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return strncpy (d, s0, 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
char* test_strncpy_s0_0_1 (char *d)
{
return strncpy (d, s0_0[0], 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return strncpy (d, s0_0[0], 1); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}
char* test_strncpy_s0_0_2 (char *d)
{
return strncpy (d, s0_0[0], 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" } */
return strncpy (d, s0_0[0], 2); /* { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" } */
}

View File

@ -3,7 +3,7 @@
functions when -Wstringop-overflow is disabled is -Warray-bounds
with the right wording.
{ dg-do compile }
{ dg-options "-O2 -Wall -Wno-stringop-overflow" } */
{ dg-options "-O2 -Wall -Wno-stringop-overflow -Wno-stringop-overread" } */
#define PTRDIFF_MAX __PTRDIFF_MAX__
#define SIZE_MAX __SIZE_MAX__

View File

@ -15,8 +15,8 @@ void fa0_extern (void)
{
sink (strlen (ea0.a - 2)); // { dg-warning "\\\[-Warray-bounds" }
sink (strlen (ea0.a - 1)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
sink (strlen (ea0.a)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
sink (strlen (ea0.a + 1)); // { dg-warning "\\\[-Warray-bounds" }
sink (strlen (ea0.a)); // { dg-warning "\\\[-Wstringop-overread" "pr93514" }
sink (strlen (ea0.a + 1)); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
}
static struct A0 sa0 = { 0 };
@ -25,8 +25,8 @@ void fa0_static (void)
{
sink (strlen (sa0.a - 2)); // { dg-warning "\\\[-Warray-bounds" }
sink (strlen (sa0.a - 1)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
sink (strlen (sa0.a)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
sink (strlen (sa0.a + 1)); // { dg-warning "\\\[-Warray-bounds" }
sink (strlen (sa0.a)); // { dg-warning "\\\[-Wstringop-overread" "pr93514" }
sink (strlen (sa0.a + 1)); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
}
@ -52,23 +52,23 @@ void fax_static (void)
sink (strlen (ax0.a - 2)); // { dg-warning "\\\[-Warray-bounds" }
sink (strlen (ax0.a - 1)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
sink (strlen (ax0.a));
sink (strlen (ax0.a + 1)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
sink (strlen (ax0.a + 2)); // { dg-warning "\\\[-Warray-bounds" }
sink (strlen (ax0.a + 1)); // { dg-warning "\\\[-Wstringop-overread" "pr93514" }
sink (strlen (ax0.a + 2)); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
sink (strlen (ax1.a - 2)); // { dg-warning "\\\[-Warray-bounds" }
sink (strlen (ax1.a - 1)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
sink (strlen (ax1.a));
sink (strlen (ax1.a + 1));
sink (strlen (ax1.a + 2)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
sink (strlen (ax1.a + 3)); // { dg-warning "\\\[-Warray-bounds" }
sink (strlen (ax1.a + 2)); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" "pr93514" }
sink (strlen (ax1.a + 3)); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
sink (strlen (ax2.a - 2)); // { dg-warning "\\\[-Warray-bounds" }
sink (strlen (ax2.a - 1)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
sink (strlen (ax2.a));
sink (strlen (ax2.a + 1));
sink (strlen (ax2.a + 2));
sink (strlen (ax2.a + 3)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
sink (strlen (ax2.a + 4)); // { dg-warning "\\\[-Warray-bounds" }
sink (strlen (ax2.a + 3)); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" "pr93514" }
sink (strlen (ax2.a + 4)); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
sink (strlen (ax3.a - 2)); // { dg-warning "\\\[-Warray-bounds" }
sink (strlen (ax3.a - 1)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
@ -76,6 +76,6 @@ void fax_static (void)
sink (strlen (ax3.a + 1));
sink (strlen (ax3.a + 2));
sink (strlen (ax3.a + 3));
sink (strlen (ax3.a + 4)); // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
sink (strlen (ax3.a + 5)); // { dg-warning "\\\[-Warray-bounds" }
sink (strlen (ax3.a + 4)); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" "pr93514" }
sink (strlen (ax3.a + 5)); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
}

View File

@ -1,6 +1,6 @@
/* Test -Wsizeof-pointer-memaccess warnings. */
/* { dg-do compile } */
/* { dg-options "-Wall -Wno-array-bounds -Wno-sizeof-array-argument -Wno-stringop-overflow" } */
/* { dg-options "-Wall -Wno-array-bounds -Wno-sizeof-array-argument -Wno-stringop-overflow -Wno-stringop-overread" } */
/* { dg-require-effective-target alloca } */
typedef __SIZE_TYPE__ size_t;

View File

@ -48,11 +48,18 @@ T (rindex, b + 4, '4'); // { dg-warning "missing terminating nul" "rindex" }
T (stpcpy, d, a); // { dg-warning "missing terminating nul" "stpcpy" }
T (stpncpy, d, a, 4);
T (stpncpy, d, a, 5); // { dg-warning "missing terminating nul" "stpncpy" }
T (stpncpy, d, a, 5); // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "stpncpy" }
T (stpncpy, d, a, n);
T (stpncpy, d, a + n, 4);
T (stpncpy, d, a + n, 5); // { dg-warning "missing terminating nul" "stpncpy" }
/* When the offset into an unterminated array isn't known and the bound
is less than the size of the array it suggests the access may be
constrained just right. When the bound is exactly equal to the size
of the array, then the offset would have to be zero for the access to
be safe, so a warning is justified. Otherwise, the bound is too small
and the access is definitely unsafe. */
T (stpncpy, d, a + n, 3);
T (stpncpy, d, a + n, 4); // { dg-warning "specified bound 4 may exceed the size of at most 4 of unterminated array" "stpncpy" }
T (stpncpy, d, a + n, 5); // { dg-warning "specified bound 5 exceeds the size of at most 4 of unterminated array" "stpncpy" }
T (stpncpy, d, b, 4);
T (stpncpy, d, b, 5);
@ -67,7 +74,7 @@ T (stpncpy, d, b + 3, 5);
T (stpncpy, d, b + 3, n);
T (stpncpy, d, b + 4, 1);
T (stpncpy, d, b + 4, 2); // { dg-warning "missing terminating nul" "stpncpy" }
T (stpncpy, d, b + 4, 2); // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "stpncpy" }
T (stpncpy, d, b + 4, n);
/* The following might be worth warning about since it's only safe with
n < 4. */
@ -84,7 +91,7 @@ T (strcasecmp, b, b + 4); // { dg-warning "missing terminating nul" "strcasecm
T (strcat, d, a); // { dg-warning "missing terminating nul" "strcat" }
T (strncat, d, a, 4);
T (strncat, d, a, 5); // { dg-warning "missing terminating nul" "strncat" }
T (strncat, d, a, 5); // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strncat" }
T (strncat, d, a, n);
T (strncat, d, b, n);
@ -93,7 +100,7 @@ T (strncat, d, b + 2, n);
T (strncat, d, b + 3, n);
T (strncat, d, b + 4, 0);
T (strncat, d, b + 4, 1);
T (strncat, d, b + 4, 2); // { dg-warning "missing terminating nul" "strncat" }
T (strncat, d, b + 4, 2); // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "strncat" }
/* The following should probably trigger a warning since it's only safe
when n < 2, makes little sense with n == 0, and not much more with
n == 1. */
@ -122,8 +129,8 @@ T (strncmp, s, a, 4);
/* The warning below is not issued because GCC folds strncmp calls with
the same arguments to zero before it checks for the missing nul. */
T (strncmp, a, a, 5); // { dg-warning "missing terminating nul" "pr92624" { xfail *-*-*} }
T (strncmp, a, s, 5); // { dg-warning "missing terminating nul" "strcmp" }
T (strncmp, s, a, 5); // { dg-warning "missing terminating nul" "strcmp" }
T (strncmp, a, s, 5); // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strcmp" }
T (strncmp, s, a, 5); // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strcmp" }
T (strcpy, d, a); // { dg-warning "missing terminating nul" "strcpy" }
@ -136,10 +143,10 @@ T (strspn, s, a); // { dg-warning "missing terminating nul" "strcspn"
T (strdup, a); // { dg-warning "missing terminating nul" "strdup" }
T (strndup, a, 4);
T (strndup, a, 5); // { dg-warning "missing terminating nul" "strndup" }
T (strndup, a, 5); // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strndup" }
T (strndup, b + 3, 2);
T (strndup, b + 4, 1);
T (strndup, b + 4, 2); // { dg-warning "missing terminating nul" "strndup" }
T (strndup, b + 4, 2); // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "strndup" }
T (strlen, a); // { dg-warning "missing terminating nul" "strlen" }
@ -161,11 +168,12 @@ T (__stpcpy_chk, d, a, -1); // { dg-warning "missing terminating nul"
T (__stpncpy_chk, d, a, 4, -1);
T (__stpncpy_chk, d, a, 5, -1); // { dg-warning "missing terminating nul" "stpncpy_chk" }
T (__stpncpy_chk, d, a, 5, -1); // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "stpncpy_chk" }
T (__stpncpy_chk, d, a, n, -1);
T (__stpncpy_chk, d, a + n, 4, -1);
T (__stpncpy_chk, d, a + n, 5, -1); // { dg-warning "missing terminating nul" "stpncpy_chk" }
T (__stpncpy_chk, d, a + n, 3, -1);
T (__stpncpy_chk, d, a + n, 4, -1); // { dg-warning "specified bound 4 may exceed the size of at most 4 of unterminated array" "stpncpy_chk" }
T (__stpncpy_chk, d, a + n, 5, -1); // { dg-warning "specified bound 5 exceeds the size of at most 4 of unterminated array" "stpncpy_chk" }
T (__stpncpy_chk, d, b, 4, -1);
T (__stpncpy_chk, d, b, 5, -1);
@ -180,16 +188,17 @@ T (__stpncpy_chk, d, b + 3, 5, -1);
T (__stpncpy_chk, d, b + 3, n, -1);
T (__stpncpy_chk, d, b + 4, 1, -1);
T (__stpncpy_chk, d, b + 4, 2, -1); // { dg-warning "missing terminating nul" "stpncpy_chk" }
T (__stpncpy_chk, d, b + 4, 2, -1); // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "stpncpy_chk" }
T (__stpncpy_chk, d, b + 4, n, -1);
T (__strncat_chk, d, a, 4, -1);
T (__strncat_chk, d, a, 5, -1); // { dg-warning "missing terminating nul" "strncat_chk" }
T (__strncat_chk, d, a, 5, -1); // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strncat_chk" }
T (__strncat_chk, d, a, n, -1);
T (__strncat_chk, d, a + n, 4, -1);
T (__strncat_chk, d, a + n, 5, -1); // { dg-warning "missing terminating nul" "strncat_chk" }
T (__strncat_chk, d, a + n, 3, -1);
T (__strncat_chk, d, a + n, 4, -1); // { dg-warning "specified bound 4 may exceed the size of at most 4 of unterminated array" "strncat_chk" }
T (__strncat_chk, d, a + n, 5, -1); // { dg-warning "specified bound 5 exceeds the size of at most 4 of unterminated array" "strncat_chk" }
T (__strncat_chk, d, b, 4, -1);
T (__strncat_chk, d, b, 5, -1);
@ -204,16 +213,17 @@ T (__strncat_chk, d, b + 3, 5, -1);
T (__strncat_chk, d, b + 3, n, -1);
T (__strncat_chk, d, b + 4, 1, -1);
T (__strncat_chk, d, b + 4, 2, -1); // { dg-warning "missing terminating nul" "strncat_chk" }
T (__strncat_chk, d, b + 4, 2, -1); // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "strncat_chk" }
T (__strncat_chk, d, b + 4, n, -1);
T (__strncpy_chk, d, a, 4, -1);
T (__strncpy_chk, d, a, 5, -1); // { dg-warning "missing terminating nul" "strncpy_chk" }
T (__strncpy_chk, d, a, 5, -1); // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strncpy_chk" }
T (__strncpy_chk, d, a, n, -1);
T (__strncpy_chk, d, a + n, 4, -1);
T (__strncpy_chk, d, a + n, 5, -1); // { dg-warning "missing terminating nul" "strncpy_chk" }
T (__strncpy_chk, d, a + n, 3, -1);
T (__strncpy_chk, d, a + n, 4, -1); // { dg-warning "specified bound 4 may exceed the size of at most 4 of unterminated array" "strncpy_chk" }
T (__strncpy_chk, d, a + n, 5, -1); // { dg-warning "specified bound 5 exceeds the size of at most 4 of unterminated array" "strncpy_chk" }
T (__strncpy_chk, d, b, 4, -1);
T (__strncpy_chk, d, b, 5, -1);
@ -228,7 +238,7 @@ T (__strncpy_chk, d, b + 3, 5, -1);
T (__strncpy_chk, d, b + 3, n, -1);
T (__strncpy_chk, d, b + 4, 1, -1);
T (__strncpy_chk, d, b + 4, 2, -1); // { dg-warning "missing terminating nul" "strncpy" }
T (__strncpy_chk, d, b + 4, 2, -1); // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "strncpy" }
T (__strncpy_chk, d, b + 4, n, -1);

View File

@ -7,7 +7,7 @@ void fcst (char *d)
{
char a[2] = "0";
__builtin_strcpy (d, a + 3); // { dg-warning "\\\[-W(array-bounds|stringop-overflow)" }
__builtin_strcpy (d, a + 3); // { dg-warning "\\\[-W(array-bounds|stringop-overread)" }
}
void frng (char *d, int i)
@ -17,14 +17,14 @@ void frng (char *d, int i)
if (i < 3)
i = 3;
__builtin_strcpy (d, a + i); // { dg-warning "\\\[-W(array-bounds|stringop-overflow)" }
__builtin_strcpy (d, a + i); // { dg-warning "\\\[-W(array-bounds|stringop-overread)" }
}
void gcst (char *d)
{
char a[2] = "0";
__builtin_strcpy (d, a + 2); // { dg-warning "\\\[-W(array-bounds|stringop-overflow)" }
__builtin_strcpy (d, a + 2); // { dg-warning "\\\[-W(array-bounds|stringop-overread)" }
}
void grng (char *d, int i)
@ -34,7 +34,7 @@ void grng (char *d, int i)
if (i < 2)
i = 2;
__builtin_strcpy (d, a + i); // { dg-warning "\\\[-W(array-bounds|stringop-overflow)" }
__builtin_strcpy (d, a + i); // { dg-warning "\\\[-W(array-bounds|stringop-overread)" }
}
/* { dg-prune-output "-Wuninitialized" } */

View File

@ -63,10 +63,10 @@ void test_strncpy (void)
char* test_strndup (void)
{
return strndup (s, SIZE_MAX - 5); /* { dg-warning ".strndup. specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+ \\\[-Wstringop-overflow=\\\]" } */
return strndup (s, SIZE_MAX - 5); /* { dg-warning ".strndup. specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+ \\\[-Wstringop-overread" } */
}
size_t test_strnlen (void)
{
return strnlen (s, SIZE_MAX - 6); /* { dg-warning ".strnlen. specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+ \\\[-Wstringop-overflow=\\\]" } */
return strnlen (s, SIZE_MAX - 6); /* { dg-warning ".strnlen. specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+ \\\[-Wstringop-overread" } */
}

View File

@ -0,0 +1,117 @@
/* Verify -Wstringop-overread is issued for reading more than the maximum
object size but not for writing.
{ dg-do compile }
{ dg-options "-O2 -Wno-stringop-overflow -ftrack-macro-expansion=0" } */
#define PTRDIFF_MAX __PTRDIFF_MAX__
#define SIZE_MAX __SIZE_MAX__
#define NOIPA __attribute__ ((noipa))
typedef __SIZE_TYPE__ size_t;
void* memchr (const void*, int, size_t);
int memcmp (const void*, const void*, size_t);
void* memcpy (const void*, const void*, size_t);
int strncmp (const char*, const char*, size_t);
char* strncat (char*, const char*, size_t);
char* strncpy (char*, const char*, size_t);
size_t strnlen (const char*, size_t);
void sink (int, ...);
#define sink(...) sink (0, __VA_ARGS__)
#define T(exp) sink (exp)
NOIPA void test_memchr (const void *p, int x)
{
size_t dmax = PTRDIFF_MAX;
size_t smax = SIZE_MAX;
T (memchr (p, x, dmax));
T (memchr (p, x, dmax + 1)); // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" }
T (memchr (p, x, dmax * 2)); // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" }
T (memchr (p, x, smax)); // { dg-warning "\\\[-Wstringop-overread" }
}
NOIPA void test_memcmp (const void *p, const void *q)
{
size_t dmax = PTRDIFF_MAX;
size_t smax = SIZE_MAX;
T (memcmp (p, q, dmax));
T (memcmp (p, q, dmax + 1)); // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" }
T (memcmp (p, q, dmax * 2)); // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" }
T (memcmp (p, q, smax)); // { dg-warning "\\\[-Wstringop-overread" }
}
NOIPA void test_memcpy (void *p, const void *q)
{
size_t dmax = PTRDIFF_MAX;
size_t smax = SIZE_MAX;
T (memcpy (p, q, dmax));
T (memcpy (p, q, dmax + 1)); // -Wstringop-overflow disabled
T (memcpy (p, q, dmax * 2)); // ditto
T (memcpy (p, q, smax)); // ditto
}
NOIPA void test_strncmp (const char *p, const char *q)
{
size_t dmax = PTRDIFF_MAX;
size_t smax = SIZE_MAX;
T (strncmp (p, q, dmax));
T (strncmp (p, q, dmax + 1)); // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" "strncmp" }
T (strncmp (p, q, dmax * 2)); // { dg-warning "\\\[-Wstringop-overread" "strncmp" }
T (strncmp (p, q, smax)); // { dg-warning "\\\[-Wstringop-overread" "strncmp" }
}
NOIPA void test_strncat (char *p, const char *q)
{
size_t dmax = PTRDIFF_MAX;
size_t smax = SIZE_MAX;
T (strncat (p, q, dmax));
T (strncat (p, q, dmax + 1)); // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" }
T (strncat (p, q, dmax * 2)); // { dg-warning "\\\[-Wstringop-overread" }
T (strncat (p, q, smax)); // { dg-warning "\\\[-Wstringop-overread" }
}
NOIPA void test_strncpy (char *p, const char *q)
{
#if 0
/* Disabled: strncpy calls with an excissve bound trigger both
-Wstringop-overflow and, when the former option is disabled,
-Wstringop-overread. The latter should probably not trigger. */
size_t dmax = PTRDIFF_MAX;
size_t smax = SIZE_MAX;
T (strncpy (p, q, dmax));
T (strncpy (p, q, dmax + 1)); // -Wstringop-overflow disabled
T (strncpy (p, q, dmax * 2)); // ditto
T (strncpy (p, q, smax)); // ditto
#endif
}
NOIPA void test_strnlen (const char *p)
{
size_t dmax = PTRDIFF_MAX;
size_t smax = SIZE_MAX;
T (strnlen (p, dmax));
T (strnlen (p, dmax + 1)); // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" }
T (strnlen (p, dmax * 2)); // { dg-warning "\\\[-Wstringop-overread" }
T (strnlen (p, smax)); // { dg-warning "\\\[-Wstringop-overread" }
}

View File

@ -0,0 +1,716 @@
/* Verify -Wstringop-overread is issued appropriately.
{ dg-do compile }
{ dg-options "-O2 -ftrack-macro-expansion=0" } */
typedef __SIZE_TYPE__ size_t;
// <libint.h> functions.
char* gettext (const char *);
// <stdio.h> functions.
int puts (const char*);
int puts_unlocked (const char*);
// <string.h> functions.
char* strchr (const char*, int);
int strcmp (const char*, const char*);
int strncmp (const char*, const char*, size_t);
char* strcat (char*, const char*);
char* strcpy (char*, const char*);
char* strncpy (char*, const char*, size_t);
char* strdup (const char*);
char* strndup (const char*, size_t);
char* strpbrk (char*, const char*);
size_t strcspn (const char*, const char*);
size_t strspn (const char*, const char*);
char* strstr (char*, const char*);
size_t strlen (const char*);
size_t strnlen (const char*, size_t);
void sink (int, ...);
#define sink(...) sink (0, __VA_ARGS__)
extern char *d;
extern char a0[0]; // { dg-message "source object 'a0'" }
extern char a1[1]; // { dg-message "source object 'a1'" }
extern char a2[2]; // { dg-message "source object 'a2'" }
extern char b1[1];
extern char b2[2];
extern char bx[];
const char s0[0] = { }; // { dg-message "source object 's0'" }
const char s1[1] = ""; // { dg-message "source object 's1'" }
const char s2[2] = "1"; // { dg-message "source object 's2'" }
#define T(x) sink (0, (x))
void test_strcat_array (const char *s, int i, int i0)
{
if (i0 < 0)
i0 = 0;
T (strcat (d, a0)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
T (strcat (d, a0 + i)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
T (strcat (d, a0 + i + 1)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
T (strcat (d, a0 + i0)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
T (strcat (d, a1));
T (strcat (d, a1 + 1)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
T (strcat (d, a1 + i));
T (strcat (d, a1 + i + 1));
T (strcat (d, a1 + i0));
T (strcat (d, a1 + i0 + 1)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
T (strcat (d, a2));
T (strcat (d, a2 + 1));
T (strcat (d, a2 + 2)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
T (strcat (d, a2 + i));
T (strcat (d, a2 + i + 2));
T (strcat (d, a2 + i0));
T (strcat (d, a2 + i0 + 1));
T (strcat (d, a2 + i0 + 2)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
// Repeat the above with the arguments reversed.
T (strcat (a0, s)); // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" }
T (strcat (a0 + i, s)); // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" }
T (strcat (a0 + i + 1, s)); // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" }
T (strcat (a0 + i0, s)); // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" }
T (strcat (a1, s));
T (strcat (a1 + 1, s)); // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" }
T (strcat (a1 + i, s));
T (strcat (a1 + i + 1, s));
T (strcat (a1 + i0, s));
T (strcat (a1 + i0 + 1, s)); // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" }
T (strcat (a2, s));
T (strcat (a2 + 1, s));
T (strcat (a2 + 2, s)); // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" }
T (strcat (a2 + i, s));
T (strcat (a2 + i + 2, s));
T (strcat (a2 + i0, s));
T (strcat (a2 + i0 + 1, s));
T (strcat (a2 + i0 + 2, s)); // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" }
}
void test_strcat_literal (int i)
{
T (strcat (d, ""));
T (strcat (d, "" + 0));
T (strcat (d, "" + i));
T (strcat (d, "1"));
T (strcat (d, "1" + 1));
T (strcat (d, "1" + 2)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
T (strcat (d, "1" + i));
T (strcat (d, "12"));
T (strcat (d, "12" + 1));
T (strcat (d, "12" + 2));
T (strcat (d, "12" + 3)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
T (strcat (d, "12" + i));
}
void test_strcat_string (int i)
{
T (strcat (d, s0)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
T (strcat (d, s0 + 1)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
T (strcat (d, s0 + i)); // { dg-warning "'strcat' (reading 1 or more bytes from a region of size 0|argument missing terminating nul)" }
T (strcat (d, s1));
T (strcat (d, s1 + 1)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
T (strcat (d, s1 + 2)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
T (strcat (d, s1 + i));
T (strcat (d, s2));
T (strcat (d, s2 + 1));
T (strcat (d, s2 + 2)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
T (strcat (d, s2 + 3)); // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
T (strcat (d, s2 + i));
}
void test_strcpy_array (int i, int i0)
{
if (i0 < 0)
i0 = 0;
T (strcpy (d, a0)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
T (strcpy (d, a0 + i)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
T (strcpy (d, a0 + i + 1)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
T (strcpy (d, a0 + i0)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
T (strcpy (d, a1));
T (strcpy (d, a1 + 1)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
T (strcpy (d, a1 + i));
T (strcpy (d, a1 + i + 1));
T (strcpy (d, a1 + i0));
T (strcpy (d, a1 + i0 + 1)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
T (strcpy (d, a2));
T (strcpy (d, a2 + 1));
T (strcpy (d, a2 + 2)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
T (strcpy (d, a2 + i));
T (strcpy (d, a2 + i + 2));
T (strcpy (d, a2 + i0));
T (strcpy (d, a2 + i0 + 1));
T (strcpy (d, a2 + i0 + 2)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
}
void test_strcpy_literal (int i)
{
T (strcpy (d, ""));
T (strcpy (d, "" + 0));
T (strcpy (d, "" + i));
T (strcpy (d, "1"));
T (strcpy (d, "1" + 1));
T (strcpy (d, "1" + 2)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
T (strcpy (d, "1" + i));
T (strcpy (d, "12"));
T (strcpy (d, "12" + 1));
T (strcpy (d, "12" + 2));
T (strcpy (d, "12" + 3)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
T (strcpy (d, "12" + i));
}
void test_strcpy_string (int i)
{
T (strcpy (d, s0)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
T (strcpy (d, s0 + 1)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
T (strcpy (d, s0 + i)); // { dg-warning "'strcpy' (reading 1 or more bytes from a region of size 0|argument missing terminating nul)" }
T (strcpy (d, s1));
T (strcpy (d, s1 + 1)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
T (strcpy (d, s1 + 2)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
T (strcpy (d, s1 + i));
T (strcpy (d, s2));
T (strcpy (d, s2 + 1));
T (strcpy (d, s2 + 2)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
T (strcpy (d, s2 + 3)); // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
T (strcpy (d, s2 + i));
}
void test_strncpy_array (int i)
{
T (strncpy (d, a0, 0));
T (strncpy (d, a0, 1)); // { dg-warning "'strncpy' reading 1 byte from a region of size 0" }
T (strncpy (d, a0 + i, 0));
T (strncpy (d, a0 + i, 1)); // { dg-warning "'strncpy' reading 1 byte from a region of size 0" }
T (strncpy (d, a1, 0));
T (strncpy (d, a1, 1));
T (strncpy (d, a1 + 1, 0));
T (strncpy (d, a1 + 1, 1)); // { dg-warning "'strncpy' reading 1 byte from a region of size 0" }
T (strncpy (d, a1 + i, 0));
T (strncpy (d, a1 + i, 1));
T (strncpy (d, a1 + i, 2));
}
void test_strncpy_literal (int i, int i0)
{
if (i0 < 0)
i0 = 0;
T (strncpy (d, "", 0));
T (strncpy (d, "", 1));
T (strncpy (d, "", 2));
T (strncpy (d, "" + i, 0));
T (strncpy (d, "" + i, 1));
T (strncpy (d, "" + i0, 1));
T (strncpy (d, "" + i0, 1));
T (strncpy (d, "" + 1, 0));
T (strncpy (d, "" + 1, 1)); // { dg-warning "'strncpy' reading 1 byte from a region of size 0" }
T (strncpy (d, "1", 0));
T (strncpy (d, "1" + 1, 0));
T (strncpy (d, "1" + 1, 1));
T (strncpy (d, "1" + 1, 2));
T (strncpy (d, "1" + i, 2));
T (strncpy (d, "1" + 2, 0));
T (strncpy (d, "1" + 2, 1)); // { dg-warning "'strncpy' reading 1 byte from a region of size 0" }
}
void test_strlen_array (int i, int i0)
{
if (i0 < 0)
i0 = 0;
T (strlen (a0)); // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" }
T (strlen (a0 + i)); // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" }
T (strlen (a0 + i + 1)); // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" }
T (strlen (a0 + i0)); // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" }
T (strlen (a1));
T (strlen (a1 + 1)); // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" }
T (strlen (a1 + i));
T (strlen (a1 + i + 1));
T (strlen (a1 + i0));
T (strlen (a1 + i0 + 1)); // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" }
T (strlen (a2));
T (strlen (a2 + 1));
T (strlen (a2 + 2)); // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" }
T (strlen (a2 + i));
T (strlen (a2 + i + 2));
T (strlen (a2 + i0));
T (strlen (a2 + i0 + 1));
T (strlen (a2 + i0 + 2)); // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" }
}
void test_strnlen_array (int i, int i0, unsigned n)
{
if (i0 < 0)
i0 = 0;
T (strnlen (a0, 0));
T (strnlen (a0, 1)); // { dg-warning "'strnlen' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" }
T (strnlen (a0, i0));
T (strnlen (a0, i0 + 1)); // { dg-warning "'strnlen' (reading between 1 and \[0-9\]+ bytes from a region of size 0|specified bound \\\[1, \[0-9\]+\\\] exceeds source size 0)" }
T (strnlen (a0, n));
T (strnlen (a0 + i, 0));
T (strnlen (a0 + i, 1)); // { dg-warning "'strnlen' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" }
T (strnlen (a0 + i, i0));
T (strnlen (a0 + i, n));
T (strnlen (a0 + i + 1, 0));
T (strnlen (a0 + i + 1, 1)); // { dg-warning "'strnlen' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" }
T (strnlen (a0 + i0, 0));
T (strnlen (a0 + i0, 1)); // { dg-warning "'strnlen' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" }
T (strnlen (a0 + i0, n));
T (strnlen (a1, 0));
T (strnlen (a1, 1));
T (strnlen (a1, 2)); // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" "pr87492" { xfail *-*-* } }
T (strnlen (a1, n));
T (strnlen (a1 + 1, 0));
T (strnlen (a1 + 1, 1)); // { dg-warning "'strnlen' reading 1 byte from a region of size 0" }
T (strnlen (a1 + 1, i0));
T (strnlen (a1 + 1, i0 + 1)); // { dg-warning "'strnlen' reading between 1 and \[0-9\]+ bytes from a region of size 0" }
T (strnlen (a1 + 1, n));
T (strnlen (a1 + i, 0));
T (strnlen (a1 + i, 1));
T (strnlen (a1 + i, 2)); // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" }
T (strnlen (a1 + i, n));
T (strnlen (a1 + i + 1, 0));
T (strnlen (a1 + i + 1, 1));
T (strnlen (a1 + i + 1, 2)); // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" }
T (strnlen (a1 + i + 1, n));
T (strnlen (a1 + i0, 0));
T (strnlen (a1 + i0, 1));
T (strnlen (a1 + i0, 2)); // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" }
T (strnlen (a1 + i0, n));
T (strnlen (a1 + i0 + 1, 0));
T (strnlen (a1 + i0 + 1, 1)); // { dg-warning "'strnlen' reading 1 byte from a region of size 0" }
T (strnlen (a1 + i0 + 1, n));
T (strnlen (a2, 0));
T (strnlen (a2, 1));
T (strnlen (a2, 2));
T (strnlen (a2, n));
T (strnlen (a2 + 1, 0));
T (strnlen (a2 + 1, 1));
T (strnlen (a2 + 1, 2)); // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" "pr87492" { xfail *-*-* } }
T (strnlen (a2 + 1, n));
T (strnlen (a2 + 2, 0));
T (strnlen (a2 + 2, 1)); // { dg-warning "'strnlen' reading 1 byte from a region of size 0" }
T (strnlen (a2 + 2, n));
T (strnlen (a2 + i, 0));
T (strnlen (a2 + i, 1));
T (strnlen (a2 + i, 2));
T (strnlen (a2 + i + 2, 0));
T (strnlen (a2 + i + 2, 1));
T (strnlen (a2 + i + 2, 2));
T (strnlen (a2 + i + 2, n));
T (strnlen (a2 + i0, 0));
T (strnlen (a2 + i0, 1));
T (strnlen (a2 + i0, 2));
T (strnlen (a2 + i0, 3)); // { dg-warning "'strnlen' specified bound 3 exceeds source size 2" }
T (strnlen (a2 + i0, n));
T (strnlen (a2 + i0 + 1, 0));
T (strnlen (a2 + i0 + 1, 1));
T (strnlen (a2 + i0 + 1, 2));
T (strnlen (a2 + i0 + 1, n));
T (strnlen (a2 + i0 + 2, 0));
T (strnlen (a2 + i0 + 2, 1)); // { dg-warning "'strnlen' reading 1 byte from a region of size 0" }
T (strnlen (a2 + i0 + 2, i0));
T (strnlen (a2 + i0 + 2, i0 + 1)); // { dg-warning "'strnlen' reading between 1 and \[0-9\]+ bytes from a region of size 0" }
T (strnlen (a2 + i0 + 2, n));
}
void test_strcmp_array (const char *s, int i)
{
T (strcmp (a0, "")); // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-* } }
T (strcmp (a0, s)); // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" }
T (strcmp (a0 + i, s)); // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" }
T (strcmp (a1, s));
T (strcmp (a1 + 1, s)); // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" }
T (strcmp (a1 + i, s));
T (strcmp (a1 + i + 1, s));
// Repeat the above with the arguments reversed.
T (strcmp ("", a0)); // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-*} }
T (strcmp (s, a0)); // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" }
T (strcmp (s, a0 + i)); // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" }
T (strcmp (s, a1));
T (strcmp (s, a1 + 1)); // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" }
T (strcmp (s, a1 + i));
T (strcmp (s, a1 + i + 1));
}
/* The number of characters read is considered to be bounded not just
by the third argument to strncmp but also by the length of the shorter
of the two strings. When the string length is unknowm, verify that
a warning is only issued for certain reading past the end but not
otherwise. */
void test_strncmp_array (const char *s, int i)
{
T (strncmp (a0, a0, 0));
T (strncmp (a0, s, 0));
T (strncmp (a0, s, 1)); // { dg-warning "'strncmp' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-* } }
T (strncmp (a0, s, 2)); // { dg-warning "'strncmp' (reading between 1 and 2 bytes from a region of size 0|specified bound 2 exceeds source size 0)" }
T (strncmp (a1, s, 0));
T (strncmp (a1, s, 1));
T (strncmp (a1 + 1, s, 1)); // { dg-warning "'strncmp' reading 1 byte from a region of size 0" "pr?????" { xfail *-*-*} }
T (strncmp (a1, s, 1));
T (strncmp (a1 + 1, s, 2)); // { dg-warning "'strncmp' (reading between 1 and 2 bytes from a region of size 0|specified bound 2 exceeds source size 0)" }
T (strncmp (a2, s, 1));
T (strncmp (a2, s, 2));
T (strncmp (a2, s, 3));
T (strncmp (a2 + 1, s, 1));
T (strncmp (a2 + 2, s, 2)); // { dg-warning "'strncmp' (reading between 1 and 2 bytes from a region of size 0|specified bound 2 exceeds source size 0)" }
T (strncmp (a1, b1, 0));
T (strncmp (a1, b1, 1));
T (strncmp (a1, b1, 2)); // { dg-warning "'strncmp' specified bound 2 exceeds source size 1" }
}
void test_strncmp_literal (const char *s, int i)
{
T (strncmp (a0, "", 0));
T (strncmp (a0, "1", 0));
T (strncmp (a0, "12", 0));
/* The calls with a bound in excess of the length of the literal are
folded early (most into strcmp) so the warning doesn't trigger. */
T (strncmp (s, "", 0));
T (strncmp (s, "1", 0));
T (strncmp (s, "1", 1));
T (strncmp (s, "1", 2)); // { dg-warning "\\\[-Wstringop-overread" "pr93665" { xfail *-*-* } }
T (strncmp (s, "12", 0));
T (strncmp (s, "12", 1));
T (strncmp (s, "12", 2));
T (strncmp (s, "12", 3)); // { dg-warning "\\\[-Wstringop-overread" "pr93665" { xfail *-*-* } }
T (strncmp (s, "123", 0));
T (strncmp (s, "123", 1));
T (strncmp (s, "123", 2));
T (strncmp (s, "123", 3));
T (strncmp (s, "123", 4)); // { dg-warning "\\\[-Wstringop-overread" "pr93665" { xfail *-*-* } }
}
void test_strchr_array (int x, int i)
{
T (strchr (a0, x)); // { dg-warning "'strchr' reading 1 or more bytes from a region of size 0" }
T (strchr (a0 + i, x)); // { dg-warning "'strchr' reading 1 or more bytes from a region of size 0" }
T (strchr (a1, x));
T (strchr (a1 + 1, x)); // { dg-warning "'strchr' reading 1 or more bytes from a region of size 0" }
T (strchr (a1 + i, x));
T (strchr (a1 + i + 1, x));
}
void test_strdup_array (int i)
{
T (strdup (a0)); // { dg-warning "'strdup' reading 1 or more bytes from a region of size 0" }
T (strdup (a0 + i)); // { dg-warning "'strdup' reading 1 or more bytes from a region of size 0" }
T (strdup (a1));
T (strdup (a1 + 1)); // { dg-warning "'strdup' reading 1 or more bytes from a region of size 0" }
T (strdup (a1 + i));
T (strdup (a1 + i + 1));
}
void test_strndup_array (int i, int i0, unsigned n)
{
if (i0 < 0)
i0 = 0;
T (strndup (a0, 0));
T (strndup (a0, 1)); // { dg-warning "'strndup' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" }
T (strndup (a0, i0));
T (strndup (a0, i0 + 1)); // { dg-warning "'strndup' (reading between 1 and \[0-9\]+ bytes from a region of size 0|specified bound \\\[1, \[0-9\]+\\\] exceeds source size 0)" }
T (strndup (a0, n));
T (strndup (a0 + i, 0));
T (strndup (a0 + i, 1)); // { dg-warning "'strndup' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" }
T (strndup (a0 + i, i0));
T (strndup (a0 + i, n));
T (strndup (a0 + i + 1, 0));
T (strndup (a0 + i + 1, 1)); // { dg-warning "'strndup' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" }
T (strndup (a0 + i0, 0));
T (strndup (a0 + i0, 1)); // { dg-warning "'strndup' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" }
T (strndup (a0 + i0, n));
T (strndup (a1, 0));
T (strndup (a1, 1));
T (strndup (a1, 2)); // { dg-warning "'strndup' specified bound 2 exceeds source size 1" }
T (strndup (a1, n));
T (strndup (a1 + 1, 0));
T (strndup (a1 + 1, 1)); // { dg-warning "'strndup' reading 1 byte from a region of size 0" }
T (strndup (a1 + 1, i0));
T (strndup (a1 + 1, i0 + 1)); // { dg-warning "'strndup' reading between 1 and \[0-9\]+ bytes from a region of size 0" }
T (strndup (a1 + 1, n));
T (strndup (a1 + i, 0));
T (strndup (a1 + i, 1));
T (strndup (a1 + i, 2)); // { dg-warning "'strndup' specified bound 2 exceeds source size 1" }
T (strndup (a1 + i, n));
T (strndup (a1 + i + 1, 0));
T (strndup (a1 + i + 1, 1));
T (strndup (a1 + i + 1, 2)); // { dg-warning "'strndup' specified bound 2 exceeds source size 1" }
T (strndup (a1 + i + 1, n));
T (strndup (a1 + i0, 0));
T (strndup (a1 + i0, 1));
T (strndup (a1 + i0, n));
T (strndup (a1 + i0 + 1, 0));
T (strndup (a1 + i0 + 1, 1)); // { dg-warning "'strndup' reading 1 byte from a region of size 0" }
T (strndup (a1 + i0 + 1, n));
T (strndup (a2, 0));
T (strndup (a2, 1));
T (strndup (a2, 2));
T (strndup (a2, n));
T (strndup (a2 + 1, 0));
T (strndup (a2 + 1, 1));
T (strndup (a2 + 1, 2));
T (strndup (a2 + 1, n));
T (strndup (a2 + 2, 0));
T (strndup (a2 + 2, 1)); // { dg-warning "'strndup' reading 1 byte from a region of size 0" }
T (strndup (a2 + 2, n));
T (strndup (a2 + i, 0));
T (strndup (a2 + i, 1));
T (strndup (a2 + i, 2));
T (strndup (a2 + i + 2, 0));
T (strndup (a2 + i + 2, 1));
T (strndup (a2 + i + 2, 2));
T (strndup (a2 + i + 2, n));
T (strndup (a2 + i0, 0));
T (strndup (a2 + i0, 1));
T (strndup (a2 + i0, 2));
T (strndup (a2 + i0, 3)); // { dg-warning "'strndup' specified bound 3 exceeds source size 2" }
T (strndup (a2 + i0, n));
T (strndup (a2 + i0 + 1, 0));
T (strndup (a2 + i0 + 1, 1));
T (strndup (a2 + i0 + 1, 2));
T (strndup (a2 + i0 + 1, n));
T (strndup (a2 + i0 + 2, 0));
T (strndup (a2 + i0 + 2, 1)); // { dg-warning "'strndup' reading 1 byte from a region of size 0" }
T (strndup (a2 + i0 + 2, i0));
T (strndup (a2 + i0 + 2, i0 + 1)); // { dg-warning "'strndup' reading between 1 and \[0-9\]+ bytes from a region of size 0" }
T (strndup (a2 + i0 + 2, n));
}
void test_strpbrk_array (char *s, int i)
{
T (strpbrk (a0, "")); // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-* } }
T (strpbrk (a0, s)); // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" }
T (strpbrk (a0 + i, s)); // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" }
T (strpbrk (a1, s));
T (strpbrk (a1 + 1, s)); // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" }
T (strpbrk (a1 + i, s));
T (strpbrk (a1 + i + 1, s));
// Repeat the above with the arguments reversed.
T (strpbrk ("", a0)); // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" }
T (strpbrk (s, a0)); // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" }
T (strpbrk (s, a0 + i)); // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" }
T (strpbrk (s, a1));
T (strpbrk (s, a1 + 1)); // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" }
T (strpbrk (s, a1 + i));
T (strpbrk (s, a1 + i + 1));
}
void test_strspn_array (const char *s, int i)
{
T (strspn (a0, "")); // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-* } }
T (strspn (a0, s)); // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" }
T (strspn (a0 + i, s)); // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" }
T (strspn (a1, s));
T (strspn (a1 + 1, s)); // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" }
T (strspn (a1 + i, s));
T (strspn (a1 + i + 1, s));
// Repeat the above with the arguments reversed.
T (strspn ("", a0)); // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-*} }
T (strspn (s, a0)); // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" }
T (strspn (s, a0 + i)); // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" }
T (strspn (s, a1));
T (strspn (s, a1 + 1)); // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" }
T (strspn (s, a1 + i));
T (strspn (s, a1 + i + 1));
}
void test_strcspn_array (const char *s, int i)
{
/* The call below is tranformed to strlen() so the warning references
the latter function instead of strcspn. Avoid testing that aspect. */
T (strcspn (a0, "")); // { dg-warning "reading 1 or more bytes from a region of size 0" }
T (strcspn (a0, s)); // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" }
T (strcspn (a0 + i, s)); // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" }
T (strcspn (a1, s));
T (strcspn (a1 + 1, s)); // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" }
T (strcspn (a1 + i, s));
T (strcspn (a1 + i + 1, s));
// Repeat the above with the arguments reversed.
T (strcspn ("", a0)); // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-*} }
T (strcspn (s, a0)); // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" }
T (strcspn (s, a0 + i)); // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" }
T (strcspn (s, a1));
T (strcspn (s, a1 + 1)); // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" }
T (strcspn (s, a1 + i));
T (strcspn (s, a1 + i + 1));
}
void test_strstr_array (char *s, int i)
{
T (strstr (a0, "")); // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-* } }
T (strstr (a0, s)); // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" }
T (strstr (a0 + i, s)); // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" }
T (strstr (a1, s));
T (strstr (a1 + 1, s)); // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" }
T (strstr (a1 + i, s));
T (strstr (a1 + i + 1, s));
// Repeat the above with the arguments reversed.
T (strstr ("", a0)); // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" }
T (strstr (s, a0)); // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" }
T (strstr (s, a0 + i)); // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" }
T (strstr (s, a1));
T (strstr (s, a1 + 1)); // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" }
T (strstr (s, a1 + i));
T (strstr (s, a1 + i + 1));
}
void test_puts_array (int i)
{
T (puts (a0)); // { dg-warning "'puts' reading 1 or more bytes from a region of size 0" }
T (puts (a0 + i)); // { dg-warning "'puts' reading 1 or more bytes from a region of size 0" }
T (puts (a1));
T (puts (a1 + 1)); // { dg-warning "'puts' reading 1 or more bytes from a region of size 0" }
T (puts (a1 + i));
T (puts (a1 + i + 1));
}
void test_puts_unlocked_array (int i)
{
T (puts_unlocked (a0)); // { dg-warning "'puts_unlocked' reading 1 or more bytes from a region of size 0" }
T (puts_unlocked (a0 + i)); // { dg-warning "'puts_unlocked' reading 1 or more bytes from a region of size 0" }
T (puts_unlocked (a1));
T (puts_unlocked (a1 + 1)); // { dg-warning "'puts_unlocked' reading 1 or more bytes from a region of size 0" }
T (puts_unlocked (a1 + i));
T (puts_unlocked (a1 + i + 1));
}
void test_gettext_array (int i)
{
T (gettext (a0)); // { dg-warning "'gettext' reading 1 or more bytes from a region of size 0" }
T (gettext (a0 + i)); // { dg-warning "'gettext' reading 1 or more bytes from a region of size 0" }
T (gettext (a1));
T (gettext (a1 + 1)); // { dg-warning "'gettext' reading 1 or more bytes from a region of size 0" }
T (gettext (a1 + i));
T (gettext (a1 + i + 1));
}

View File

@ -26,8 +26,8 @@ void test_strnlen_array_cst (void)
T (strnlen (ns3, 1));
T (strnlen (ns3, 2));
T (strnlen (ns3, 3));
T (strnlen (ns3, 4)); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound 4" } */
T (strnlen (ns3, DIFF_MAX)); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound \[0-9\]+" } */
T (strnlen (ns3, 4)); /* { dg-warning "specified bound 4 exceeds source size 3" } */
T (strnlen (ns3, DIFF_MAX)); /* { dg-warning "specified bound \[0-9\]+ exceeds source size" } */
T (strnlen (ns3, SIZE_MAX)); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
NONSTRING char ns5[5];
@ -37,8 +37,8 @@ void test_strnlen_array_cst (void)
T (strnlen (ns5, 1));
T (strnlen (ns5, 2));
T (strnlen (ns5, 3));
T (strnlen (ns5, 6)); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound 6" } */
T (strnlen (ns5, DIFF_MAX)); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound \[0-9\]+" } */
T (strnlen (ns5, 6)); /* { dg-warning "specified bound 6 exceeds source size 5" } */
T (strnlen (ns5, DIFF_MAX)); /* { dg-warning "specified bound \[0-9\]+ exceeds source size 5" } */
T (strnlen (ns5, SIZE_MAX)); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
}
@ -52,8 +52,8 @@ void test_strnlen_array_range (void)
T (strnlen (ns3, UR (0, 9)));
T (strnlen (ns3, UR (3, 4)));
T (strnlen (ns3, UR (3, DIFF_MAX)));
T (strnlen (ns3, UR (4, 5))); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound \\\[4, 5]" } */
T (strnlen (ns3, UR (DIFF_MAX, SIZE_MAX))); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller " } */
T (strnlen (ns3, UR (4, 5))); /* { dg-warning "specified bound \\\[4, 5] exceeds source size 3" } */
T (strnlen (ns3, UR (DIFF_MAX, SIZE_MAX))); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds source size 3 " } */
}
@ -73,8 +73,8 @@ void test_strnlen_string_cst (void)
T (3, "12", 3, 1);
T (3, "12", 3, 9);
T (3, "123", 3, 1);
T (3, "123", 3, 4); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound 4" } */
T (3, "123", 3, 9); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound 9" } */
T (3, "123", 3, 4); /* { dg-warning "specified bound 4 exceeds source size 3" } */
T (3, "123", 3, 9); /* { dg-warning "specified bound 9 exceeds source size 3" } */
T (5, "1", 2, 1);
T (5, "1", 2, 2);
@ -84,7 +84,7 @@ void test_strnlen_string_cst (void)
T (5, "12", 3, 9);
T (5, "123", 3, 1);
T (5, "123", 3, 5);
T (5, "123", 3, 6); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound 6" } */
T (5, "123", 3, 6); /* { dg-warning "specified bound 6 exceeds source size 5" } */
/* Strnlen shouldn't trigger a warning for arrays of unknown size
(except for accesses to uninitialized elements when those are
@ -110,6 +110,6 @@ void test_strnlen_string_range (void)
{
T (3, "1", 2, UR (0, 1));
T (3, "1", 2, UR (3, 9));
T (3, "123", 3, UR (4, 5)); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound \\\[4, 5]" } */
T (3, "123", 3, UR (5, 9)); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound \\\[5, 9]" } */
T (3, "123", 3, UR (4, 5)); /* { dg-warning "specified bound \\\[4, 5] exceeds source size 3" } */
T (3, "123", 3, UR (5, 9)); /* { dg-warning "specified bound \\\[5, 9] exceeds source size 3" } */
}

View File

@ -37,15 +37,21 @@ void strncmp_cst (void)
T (STR, /* [] */, STR, /* [] */, n);
T (STR, /* [] */, STR, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
T (STR, 1, STR, /* [] */, 1);
T (STR, 1, STR, /* [] */, n);
T (STR, 2, STR, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
T (STR, /* [] */, STR, 3, 3);
T (STR, /* [] */, STR, 3, n);
T (STR, /* [] */, STR, 4, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
T (STR, /* [] */, NS, /* [] */, 3);
T (STR, /* [] */, NS, /* [] */, n);
T (STR, /* [] */, NS, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
T (STR, 5, NS, /* [] */, 4);
T (STR, 5, NS, /* [] */, 5);
T (STR, 5, NS, /* [] */, 6);
T (STR, 5, NS, /* [] */, n);
T (STR, 6, NS, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
@ -56,19 +62,22 @@ void strncmp_cst (void)
T (NS, /* [] */, STR, /* [] */, n);
T (NS, /* [] */, STR, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
T (NS, 9, STR, /* [] */, n); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound" } */
T (NS, 9, STR, /* [] */, n); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound \[0-9\]+" } */
T (NS, 10, STR, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
T (NS, /* [] */, STR, 11, 11);
T (NS, /* [] */, STR, 11, n);
T (NS, /* [] */, STR, 12, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
T (NS, /* [] */, NS, /* [] */, n);
T (NS, /* [] */, NS, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
T (NS, 13, NS, /* [] */, n); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound" } */
T (NS, 13, NS, /* [] */, 13);
T (NS, 13, NS, /* [] */, n); /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound \[0-9\]+" } */
T (NS, 14, NS, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
T (NS, /* [] */, NS, 15, n); /* { dg-warning "argument 2 declared attribute .nonstring. is smaller than the specified bound" } */
T (NS, /* [] */, NS, 15, 15);
T (NS, /* [] */, NS, 15, 16); /* { dg-warning "argument 2 declared attribute 'nonstring' is smaller than the specified bound 16" } */
T (NS, /* [] */, NS, 16, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
}
@ -81,6 +90,7 @@ void strncmp_range (void)
T (STR, /* [] */, STR, /* [] */, n);
T (STR, /* [] */, STR, /* [] */, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */
T (STR, 1, STR, /* [] */, 1);
T (STR, 1, STR, /* [] */, n);
T (STR, 2, STR, /* [] */, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */
@ -93,7 +103,7 @@ void strncmp_range (void)
T (STR, 5, NS, /* [] */, n);
T (STR, 6, NS, /* [] */, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */
T (STR, /* [] */, NS, 7, n); /* { dg-warning "argument 2 declared attribute .nonstring. is smaller than the specified bound" } */
T (STR, /* [] */, NS, 7, n); /* { dg-warning "argument 2 declared attribute 'nonstring' is smaller than the specified bound \\\[\[0-9\]+, \[0-9\]+]" } */
T (STR, /* [] */, NS, 8, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */

View File

@ -40,7 +40,7 @@ void strnlen_cst (void)
T (NS, /* [] */, n);
T (NS, /* [] */, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
T (NS, 9, n); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound" } */
T (NS, 9, n); /* { dg-warning "specified bound \[0-9\]+ exceeds source size 9" } */
T (NS, 10, n + 1); /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
}
@ -53,12 +53,12 @@ void strnlen_range (void)
T (STR, /* [] */, n);
T (STR, /* [] */, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */
T (STR, 1, n);
T (STR, 1, n); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds source size 1" } */
T (STR, 2, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */
T (NS, /* [] */, n);
T (NS, /* [] */, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */
T (NS, 9, n); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound" } */
T (NS, 9, n); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds source size 9" } */
T (NS, 10, n + 1); /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size \[0-9\]+" } */
}

View File

@ -44,80 +44,80 @@ int strcmp_nonstring_1 (NONSTRING const char *a, const char *b)
no good on its own. Use dg-regexp instead to verify that just
one instance of the warning is issued. See gcc.dg/pr64223-1
for a different approach. */
return strcmp (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strcmp. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strcmp" } */
return strcmp (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strcmp. argument 1 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strcmp" } */
}
int strcmp_nonstring_2 (const char *a, NONSTRING const char *b)
{
return strcmp (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strcmp. argument 2 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strcmp" } */
return strcmp (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strcmp. argument 2 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strcmp" } */
}
int strncmp_nonstring_1 (const char *s)
{
return strncmp (s, ns5, sizeof ns5 + 1); /* { dg-regexp "\[^\n\r\]+: warning: .strncmp. argument 2 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overflow=]" "strncmp" } */
return strncmp (s, ns5, sizeof ns5 + 1); /* { dg-regexp "\[^\n\r\]+: warning: .strncmp. argument 2 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overread\[^\n\r\]*" "strncmp" } */
}
int strncmp_nonstring_2 (const char *s)
{
return strncmp (ns5, s, sizeof ns5 + 1); /* { dg-regexp "\[^\n\r\]+: warning: .strncmp. argument 1 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overflow=]" "strncmp" } */
return strncmp (ns5, s, sizeof ns5 + 1); /* { dg-regexp "\[^\n\r\]+: warning: .strncmp. argument 1 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overread\[^\n\r\]*" "strncmp" } */
}
char* stpcpy_nonstring (char *d, NONSTRING const char *s)
{
return stpcpy (d, s); /* { dg-regexp "\[^\n\r\]+: warning: .stpcpy. argument 2 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "stpcpy" } */
return stpcpy (d, s); /* { dg-regexp "\[^\n\r\]+: warning: .stpcpy. argument 2 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "stpcpy" } */
}
char* stpncpy_nonstring (char *d)
{
return stpncpy (d, ns5, sizeof ns5 + 1); /* { dg-regexp "\[^\n\r\]+: warning: .stpncpy. argument 2 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overflow=]" "stpncpy" } */
return stpncpy (d, ns5, sizeof ns5 + 1); /* { dg-regexp "\[^\n\r\]+: warning: .stpncpy. argument 2 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overread\[^\n\r\]*" "stpncpy" } */
}
char* strchr_nonstring (NONSTRING const char *s, int c)
{
return strchr (s, c); /* { dg-regexp "\[^\n\r\]+: warning: .strchr. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strchr" } */
return strchr (s, c); /* { dg-regexp "\[^\n\r\]+: warning: .strchr. argument 1 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strchr" } */
}
char* strrchr_nonstring (NONSTRING const char *s, int c)
{
return strrchr (s, c); /* { dg-regexp "\[^\n\r\]+: warning: .strrchr. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strrchr" } */
return strrchr (s, c); /* { dg-regexp "\[^\n\r\]+: warning: .strrchr. argument 1 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strrchr" } */
}
char* strcpy_nonstring (char *d, NONSTRING const char *s)
{
return strcpy (d, s); /* { dg-regexp "\[^\n\r\]+: warning: .strcpy. argument 2 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strcpy" } */
return strcpy (d, s); /* { dg-regexp "\[^\n\r\]+: warning: .strcpy. argument 2 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strcpy" } */
}
char* strncpy_nonstring (char *d)
{
return strncpy (d, ns5, sizeof ns5 + 1); /* { dg-regexp "\[^\n\r\]+: warning: .strncpy. argument 2 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overflow=]" "strncpy" } */
return strncpy (d, ns5, sizeof ns5 + 1); /* { dg-regexp "\[^\n\r\]+: warning: .strncpy. argument 2 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overread\[^\n\r\]*" "strncpy" } */
}
char* strstr_nonstring_1 (NONSTRING const char *a, const char *b)
{
return strstr (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strstr. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strstr" } */
return strstr (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strstr. argument 1 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strstr" } */
}
char* strstr_nonstring_2 (const char *a, NONSTRING const char *b)
{
return strstr (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strstr. argument 2 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strstr" } */
return strstr (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strstr. argument 2 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strstr" } */
}
char* stdup_nonstring (NONSTRING const char *s)
{
return strdup (s); /* { dg-regexp "\[^\n\r\]+: warning: .strdup. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strdup" } */
return strdup (s); /* { dg-regexp "\[^\n\r\]+: warning: .strdup. argument 1 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strdup" } */
}
size_t strlen_nonstring (NONSTRING const char *s)
{
return strlen (s); /* { dg-regexp "\[^\n\r\]+: warning: .strlen. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strlen" } */
return strlen (s); /* { dg-regexp "\[^\n\r\]+: warning: .strlen. argument 1 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "strlen" } */
}
int printf_nonstring (NONSTRING const char *s)
{
return printf (s); /* { dg-regexp "\[^\n\r\]+: warning: .printf. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "printf" } */
return printf (s); /* { dg-regexp "\[^\n\r\]+: warning: .printf. argument 1 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "printf" } */
}
int sprintf_nonstring_2 (char *d, NONSTRING const char *s)
{
return sprintf (d, s); /* { dg-regexp "\[^\n\r\]+: warning: .sprintf. argument 2 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "sprintf" } */
return sprintf (d, s); /* { dg-regexp "\[^\n\r\]+: warning: .sprintf. argument 2 declared attribute .nonstring. \\\[-Wstringop-overread\[^\n\r\]*" "sprintf" } */
}

View File

@ -87,7 +87,7 @@ void test_memop_warn_local (const void *src)
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
/* Same as above but clearing just members 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);

View File

@ -1,6 +1,6 @@
/* Test exercising -Wstringop-overflow warnings for reading past the end. */
/* Test exercising -Wstringop-overread warnings for reading past the end. */
/* { dg-do compile } */
/* { dg-options "-O2 -Wstringop-overflow=1 -ftrack-macro-expansion=0" } */
/* { dg-options "-O2 -Wstringop-overread -ftrack-macro-expansion=0" } */
#define PTRDIFF_MAX __PTRDIFF_MAX__
#define SIZE_MAX __SIZE_MAX__
@ -73,22 +73,22 @@ void test_memop_warn_local (void *p, const void *q)
/* Verify memchr/memcmp. */
int i = R (0, 255);
memchr ("", i, 2); /* { dg-warning "reading 2 bytes from a region of size 1" } */
memchr ("", i, 2); /* { dg-warning "reading 2 bytes from a region of size 1" } */
memchr ("123", i, 5); /* { dg-warning "reading 5 bytes from a region of size 4" } */
memchr (a, i, sizeof a + 1); /* { dg-warning "reading 5 bytes from a region of size 4" } */
memchr ("", i, 2); /* { dg-warning "specified bound 2 exceeds source size 1" "memchr" } */
memchr ("", i, 2); /* { dg-warning "specified bound 2 exceeds source size 1" "memchr" } */
memchr ("123", i, 5); /* { dg-warning "specified bound 5 exceeds source size 4" "memchr" } */
memchr (a, i, sizeof a + 1); /* { dg-warning "specified bound 5 exceeds source size 4" "memchr" } */
memcmp (p, "", 2); /* { dg-warning "reading 2 bytes from a region of size 1" } */
memcmp (p, "123", 5); /* { dg-warning "reading 5 bytes from a region of size 4" } */
memcmp (p, a, sizeof a + 1); /* { dg-warning "reading 5 bytes from a region of size 4" } */
memcmp (p, "", 2); /* { dg-warning "specified bound 2 exceeds source size 1" "memcmp" } */
memcmp (p, "123", 5); /* { dg-warning "specified bound 5 exceeds source size 4" "memcmp" } */
memcmp (p, a, sizeof a + 1); /* { dg-warning "specified bound 5 exceeds source size 4" "memcmp" } */
size_t n = PTRDIFF_MAX + (size_t)1;
memchr (p, 1, n); /* { dg-warning "exceeds maximum object size" } */
memcmp (p, q, n); /* { dg-warning "exceeds maximum object size" } */
memchr (p, 1, n); /* { dg-warning "exceeds maximum object size" "memchr" } */
memcmp (p, q, n); /* { dg-warning "exceeds maximum object size" "memcmp" } */
n = SIZE_MAX;
memchr (p, 1, n); /* { dg-warning "exceeds maximum object size" } */
memcmp (p, q, n); /* { dg-warning "exceeds maximum object size" } */
memchr (p, 1, n); /* { dg-warning "exceeds maximum object size" "memchr" } */
memcmp (p, q, n); /* { dg-warning "exceeds maximum object size" "memcmp" } */
}
/* Verify that reading beyond the end of a dynamically allocated array
@ -117,8 +117,8 @@ void test_memop_warn_alloc (void *p)
/* Verify memchr/memcmp. */
n = sizeof *b * 2 + 1;
memchr (b, 1, n); /* { dg-warning "reading 9 bytes from a region of size 8" "memcmp from allocated" } */
memcmp (p, b, n); /* { dg-warning "reading 9 bytes from a region of size 8" "memcmp from allocated" } */
memchr (b, 1, n); /* { dg-warning "specified bound 9 exceeds source size 8" "memchr from allocated" } */
memcmp (p, b, n); /* { dg-warning "specified bound 9 exceeds source size 8" "memcmp from allocated" } */
}

View File

@ -12,4 +12,5 @@ void foo(void)
__builtin_aligned_alloc (10, 16); /* { dg-warning "ignoring return value of '__builtin_aligned_alloc' declared with attribute 'warn_unused_result'" } */
__builtin_strdup ("pes"); /* { dg-warning "ignoring return value of '__builtin_strdup' declared with attribute 'warn_unused_result'" } */
__builtin_strndup ("pes", 10); /* { dg-warning "ignoring return value of '__builtin_strndup' declared with attribute 'warn_unused_result'" } */
/* { dg-warning "\\\[-Wstringop-overread" "strndup excessive bound" { target *-*-* } .-1 } */
}

View File

@ -84,5 +84,5 @@ char* test_strncat (int i)
{
const char *s = i < 0 ? "123" : "4567";
return strncat (d, s, range ()); /* { dg-warning ".__builtin_strncat. specified bound between 4 and \[0-9\]+" } */
return strncat (d, s, range ()); /* { dg-warning ".__builtin_strncat. specified bound \\\[4, \[0-9\]+] exceeds destination size 3" } */
}

View File

@ -3,7 +3,7 @@
when the pointer pointed to by the enclosing object references an object
sufficiently large to store a string of equal length.
{ dg-do compile }
{ dg-options "-O2 -Wall -Wextra -fdump-tree-optimized" } */
{ dg-options "-O2 -Wall -Wextra -Wno-stringop-overread -fdump-tree-optimized" } */
void init (void*);

View File

@ -21,9 +21,9 @@ void test_var_flexarray_cst_off (void)
{
/* Use arbitrary constants greater than 16 in case GCC ever starts
unrolling strlen() calls with small array arguments. */
a[0] = 17 < strlen (a0.a + 1); // { dg-warning "\\\[-Warray-bounds" }
a[1] = 19 < strlen (a1.a + 1);
a[2] = 23 < strlen (a9.a + 9);
a[0] = 17 < strlen (a0.a + 1); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overread" }
a[1] = 19 < strlen (a1.a + 1); // { dg-warning "\\\[-Wstringop-overread" }
a[2] = 23 < strlen (a9.a + 9); // { dg-warning "\\\[-Wstringop-overread" }
a[3] = 29 < strlen (ax.a + 3);
}

View File

@ -1,6 +1,6 @@
/* Test -Wsizeof-pointer-memaccess warnings. */
/* { dg-do compile } */
/* { dg-options "-Wall -Wno-array-bounds -Wno-sizeof-array-argument -Wno-stringop-overflow -Wno-stringop-truncation" } */
/* { dg-options "-Wall -Wno-array-bounds -Wno-sizeof-array-argument -Wno-stringop-overflow -Wno-stringop-overread -Wno-stringop-truncation" } */
/* Test just twice, once with -O0 non-fortified, once with -O2 fortified. */
/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" "-O2" } } */
/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */

View File

@ -14,13 +14,13 @@ main (void)
/* MEMCHR. */
if (__builtin_memchr ("", 'x', 1000)) /* Not folded away. */
{
/* { dg-warning "reading 1000 bytes from a region of size 1" "" { target *-*-* } .-2 } */
/* { dg-warning "\\\[-Wstringop-overread" "" { target *-*-* } .-2 } */
__builtin_abort ();
}
if (__builtin_memchr (foo1, 'x', 1000)) /* Not folded away. */
{
/* { dg-warning "reading 1000 bytes from a region of size 1" "" { target *-*-* } .-2 } */
/* { dg-warning "\\\[-Wstringop-overread" "" { target *-*-* } .-2 } */
__builtin_abort ();
}

View File

@ -27,7 +27,7 @@ void nowarn_scalar_plus_fpri (void)
int i;
/* This gets a -Wstringop-overflow for reading past the end but not
-Wuninitialized because there's nothing to initialize there. */
fpri (&i + 1); // { dg-warning "\\\[-Wstringop-overflow" }
fpri (&i + 1); // { dg-warning "\\\[-Wstringop-overread" }
}
void nowarn_array_assign_fpcri (void)

View File

@ -62,5 +62,11 @@ void test (int n0)
int n = n0 < n1 ? n1 : n0;
sink (strnlen (c + n, n + 1)); /* { dg-warning "specified bound \\\[5, \[0-9\]+] may exceed the size of at most 4 of unterminated array" } */
/* N is at least 4 and c[4] is out-of-bounds. This could trigger
either -Warray-bounds or -Wstringop-overread. -Warray-bounds
only diagnoses past-the-end accesses by modifying functions
(in gimple-ssa-warn-restrict.c) and even for those, either
-Wstringop-overflow or -Wstringop-overread would be more
appropriate. */
sink (strnlen (c + n, n + 1)); /* { dg-warning "specified bound \\\[5, \[0-9\]+] exceeds the size of at most 4 of unterminated array" } */
}

View File

@ -35,7 +35,7 @@ T (&a[1], asz - 1);
T (&a[v0], asz); /* { dg-warning "specified bound 5 may exceed the size of at most 5 of unterminated array" } */
T (&a[v0] + 1, asz); /* { dg-warning "specified bound 5 may exceed the size of at most 5 of unterminated array" } */
T (a, asz + 1); /* { dg-warning "specified bound 6 exceeds the size 5 " } */
T (a, asz + 1); /* { dg-warning "specified bound 6 exceeds the size 5 of unterminated array" } */
T (&a[0], asz + 1); /* { dg-warning "unterminated" } */
T (&a[0] + 1, asz - 1);
T (&a[0] + 1, asz + 1); /* { dg-warning "unterminated" } */
@ -110,7 +110,7 @@ T (&b[3][1] + i1, bsz); /* { dg-warning "unterminated" } */
T (&b[3][1] + i1, bsz - i1); /* { dg-warning "unterminated" } */
T (&b[3][1] + i1, bsz - i2);
T (&b[3][v0], bsz);
T (&b[3][1] + v0, bsz); /* { dg-warning "specified bound 5 may exceed the size of at most 4 of unterminated array" } */
T (&b[3][1] + v0, bsz); /* { dg-warning "specified bound 5 exceeds the size of at most 4 of unterminated array" } */
T (&b[3][v0] + v1, bsz); /* { dg-warning "specified bound 5 may exceed the size of at most 4 of unterminated array" "pr?????" { xfail *-*-* } } */
T (&b[3][1], bsz + 1); /* { dg-warning "unterminated" } */
@ -124,7 +124,7 @@ T (&b[i3][i1], bsz); /* { dg-warning "unterminated" } */
T (&b[i3][i1] + 1, bsz); /* { dg-warning "unterminated" } */
T (&b[i3][i1] + i1, bsz); /* { dg-warning "specified bound 5 exceeds the size 3 of unterminated array" } */
T (&b[i3][v0], bsz);
T (&b[i3][i1] + v0, bsz); /* { dg-warning "specified bound 5 may exceed the size of at most 4 of unterminated array" } */
T (&b[i3][i1] + v0, bsz); /* { dg-warning "specified bound 5 exceeds the size of at most 4 of unterminated array" } */
T (&b[i3][v0] + v1, bsz);
T (&b[i3][i1], bsz + 1); /* { dg-warning "unterminated" } */
@ -212,10 +212,10 @@ T (&s.a[i1] + v0, asz);
T (s.a, asz + 1);
T (&s.a[0], asz + 1);
T (&s.a[0] + 1, asz + 1);
T (&s.a[0] + v0, asz + 1);
T (&s.a[0] + v0, asz + 1); /* { dg-warning "specified bound 6 exceeds source size 5 " } */
T (&s.a[1], asz + 1);
T (&s.a[1] + 1, asz + 1);
T (&s.a[1] + v0, asz + 1);
T (&s.a[1] + v0, asz + 1); /* { dg-bogus "specified bound 6 exceeds source size 5" "pr95794" { xfail *-*-* } } */
T (&s.a[i0], asz + 1);
T (&s.a[i0] + i1, asz + 1);
@ -266,10 +266,10 @@ const struct B ba[] = {
T (ba[0].a[0].a, asz + 1);
T (&ba[0].a[0].a[0], asz + 1);
T (&ba[0].a[0].a[0] + 1, asz + 1);
T (&ba[0].a[0].a[0] + v0, asz + 1);
T (&ba[0].a[0].a[0] + v0, asz + 1); /* { dg-bogus "specified bound 6 exceeds source size 5" pr95794" { xfail *-*-* } } */
T (&ba[0].a[0].a[1], asz + 1);
T (&ba[0].a[0].a[1] + 1, asz + 1);
T (&ba[0].a[0].a[1] + v0, asz + 1);
T (&ba[0].a[0].a[1] + v0, asz + 1); /* { dg-bogus "specified bound 6 exceeds source size 5" pr95794" { xfail *-*-* } } */
T (ba[0].a[0].b, bsz);
T (&ba[0].a[0].b[0], bsz);
@ -302,10 +302,10 @@ T (&ba[0].a[1].a[1] + v0, asz + 1); /* { dg-warning "unterminated" } */
T (ba[0].a[1].b, bsz + 1);
T (&ba[0].a[1].b[0], bsz + 1);
T (&ba[0].a[1].b[0] + 1, bsz + 1);
T (&ba[0].a[1].b[0] + v0, bsz + 1);
T (&ba[0].a[1].b[0] + v0, bsz + 1); /* { dg-bogus "specified bound 6 exceeds source size 5" pr95794" { xfail *-*-* } } */
T (&ba[0].a[1].b[1], bsz + 1);
T (&ba[0].a[1].b[1] + 1, bsz + 1);
T (&ba[0].a[1].b[1] + v0, bsz + 1);
T (&ba[0].a[1].b[1] + v0, bsz + 1); /* { dg-bogus "specified bound 6 exceeds source size 5" pr95794" { xfail *-*-* } } */
T (ba[1].a[0].a, asz);
T (&ba[1].a[0].a[0], asz);

View File

@ -1,7 +1,7 @@
/* When the specified length exceeds one of the arguments of the call to memcmp,
/* When the specified length exceeds one of the arguments of the call to memcmp,
the call to memcmp should NOT be inlined. */
/* { dg-do compile } */
/* { dg-options "-O2 -Wno-stringop-overflow" } */
/* { dg-options "-O2 -Wno-stringop-overread" } */
typedef struct { char s[8]; int x; } S;
@ -9,7 +9,7 @@ __attribute__ ((noinline)) int
f1 (S * s)
{
int result = 0;
result += __builtin_memcmp (s->s, "a", 3);
result += __builtin_memcmp (s->s, "a", 3);
return result;
}
@ -17,7 +17,7 @@ __attribute__ ((noinline)) int
f2 (char *p)
{
int result = 0;
result += __builtin_memcmp (p, "a", 3);
result += __builtin_memcmp (p, "a", 3);
return result;
}

View File

@ -489,10 +489,10 @@ maybe_warn_pass_by_reference (gimple *stmt, wlimits &wlims)
attr_access *access = rdwr_idx.get (argno - 1);
if (access)
{
if (access->mode == attr_access::none
|| access->mode == attr_access::write_only)
if (access->mode == access_none
|| access->mode == access_write_only)
continue;
if (save_always_executed && access->mode == attr_access::read_only)
if (save_always_executed && access->mode == access_read_only)
/* Attribute read_only arguments imply read access. */
wlims.always_executed = true;
else
@ -524,7 +524,7 @@ maybe_warn_pass_by_reference (gimple *stmt, wlimits &wlims)
if (access)
{
const char* const mode = (access->mode == attr_access::read_only
const char* const mode = (access->mode == access_read_only
? "read_only" : "read_write");
char attrstr[80];
int n = sprintf (attrstr, "access (%s, %u", mode, argno);

View File

@ -5340,6 +5340,15 @@ canonical_type_used_p (const_tree t)
|| TREE_CODE (t) == VECTOR_TYPE);
}
/* Kinds of access to pass-by-reference arguments to functions. */
enum access_mode
{
access_none = 0,
access_read_only = 1,
access_write_only = 2,
access_read_write = access_read_only | access_write_only
};
#define tree_map_eq tree_map_base_eq
extern unsigned int tree_map_hash (const void *);
#define tree_map_marked_p tree_map_base_marked_p