PR tree-optimization/78775 - [7 Regression] ICE in maybe_warn_alloc_args_overflow
gcc/ChangeLog: PR tree-optimization/78775 * builtins.c (get_size_range): Move... * calls.c: ...to here. (alloc_max_size): Accept zero argument. (operand_signed_p): Remove. (maybe_warn_alloc_args_overflow): Call get_size_range. * calls.h (get_size_range): Declare. gcc/testsuite/ChangeLog: PR tree-optimization/78775 * gcc.dg/attr-alloc_size-4.c: Add test cases. * gcc.dg/attr-alloc_size-10.c: New test. * gcc.dg/attr-alloc_size-11.c: New test. * gcc.dg/builtin-stringop-chk-7.c: New test. * gcc.dg/pr78775.c: New test. * gcc.dg/pr78973-2.c: New test. * gcc.dg/pr78973.c: New test. From-SVN: r244290
This commit is contained in:
parent
5d58291930
commit
c16880eff0
|
@ -1,3 +1,13 @@
|
||||||
|
2017-01-10 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR tree-optimization/78775
|
||||||
|
* builtins.c (get_size_range): Move...
|
||||||
|
* calls.c: ...to here.
|
||||||
|
(alloc_max_size): Accept zero argument.
|
||||||
|
(operand_signed_p): Remove.
|
||||||
|
(maybe_warn_alloc_args_overflow): Call get_size_range.
|
||||||
|
* calls.h (get_size_range): Declare.
|
||||||
|
|
||||||
2017-01-10 Joe Seymour <joe.s@somniumtech.com>
|
2017-01-10 Joe Seymour <joe.s@somniumtech.com>
|
||||||
|
|
||||||
* config/msp430/driver-msp430.c (msp430_mcu_data): Sync with data
|
* config/msp430/driver-msp430.c (msp430_mcu_data): Sync with data
|
||||||
|
|
|
@ -3031,42 +3031,6 @@ expand_builtin_memcpy_args (tree dest, tree src, tree len, rtx target, tree exp)
|
||||||
return dest_addr;
|
return dest_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill the 2-element RANGE array with the minimum and maximum values
|
|
||||||
EXP is known to have and return true, otherwise null and return
|
|
||||||
false. */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
get_size_range (tree exp, tree range[2])
|
|
||||||
{
|
|
||||||
if (tree_fits_uhwi_p (exp))
|
|
||||||
{
|
|
||||||
range[0] = range[1] = exp;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TREE_CODE (exp) == SSA_NAME)
|
|
||||||
{
|
|
||||||
wide_int min, max;
|
|
||||||
enum value_range_type range_type = get_range_info (exp, &min, &max);
|
|
||||||
|
|
||||||
if (range_type == VR_RANGE)
|
|
||||||
{
|
|
||||||
/* Interpret the bound in the variable's type. */
|
|
||||||
range[0] = wide_int_to_tree (TREE_TYPE (exp), min);
|
|
||||||
range[1] = wide_int_to_tree (TREE_TYPE (exp), max);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (range_type == VR_ANTI_RANGE)
|
|
||||||
{
|
|
||||||
/* FIXME: Handle anti-ranges. */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
range[0] = NULL_TREE;
|
|
||||||
range[1] = NULL_TREE;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try to verify that the sizes and lengths of the arguments to a string
|
/* Try to verify that the sizes and lengths of the arguments to a string
|
||||||
manipulation function given by EXP are within valid bounds and that
|
manipulation function given by EXP are within valid bounds and that
|
||||||
the operation does not lead to buffer overflow. Arguments other than
|
the operation does not lead to buffer overflow. Arguments other than
|
||||||
|
|
200
gcc/calls.c
200
gcc/calls.c
|
@ -1197,14 +1197,15 @@ alloc_max_size (void)
|
||||||
{
|
{
|
||||||
alloc_object_size_limit = TYPE_MAX_VALUE (ssizetype);
|
alloc_object_size_limit = TYPE_MAX_VALUE (ssizetype);
|
||||||
|
|
||||||
unsigned HOST_WIDE_INT unit = 1;
|
if (warn_alloc_size_limit)
|
||||||
|
{
|
||||||
char *end;
|
char *end = NULL;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
unsigned HOST_WIDE_INT unit = 1;
|
||||||
unsigned HOST_WIDE_INT limit
|
unsigned HOST_WIDE_INT limit
|
||||||
= warn_alloc_size_limit ? strtoull (warn_alloc_size_limit, &end, 10) : 0;
|
= strtoull (warn_alloc_size_limit, &end, 10);
|
||||||
|
|
||||||
if (limit && !errno)
|
if (!errno)
|
||||||
{
|
{
|
||||||
if (end && *end)
|
if (end && *end)
|
||||||
{
|
{
|
||||||
|
@ -1240,49 +1241,100 @@ alloc_max_size (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unit)
|
if (unit)
|
||||||
alloc_object_size_limit = build_int_cst (ssizetype, limit * unit);
|
alloc_object_size_limit
|
||||||
|
= build_int_cst (ssizetype, limit * unit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return alloc_object_size_limit;
|
return alloc_object_size_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return true if the type of OP is signed, looking through any casts
|
/* Return true when EXP's range can be determined and set RANGE[] to it
|
||||||
to an unsigned type. */
|
after adjusting it if necessary to make EXP a valid size argument to
|
||||||
|
an allocation function declared with attribute alloc_size (whose
|
||||||
|
argument may be signed), or to a string manipulation function like
|
||||||
|
memset. */
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
operand_signed_p (tree op)
|
get_size_range (tree exp, tree range[2])
|
||||||
{
|
{
|
||||||
if (TREE_CODE (op) == SSA_NAME)
|
if (tree_fits_uhwi_p (exp))
|
||||||
{
|
{
|
||||||
gimple *def = SSA_NAME_DEF_STMT (op);
|
/* EXP is a constant. */
|
||||||
if (is_gimple_assign (def))
|
range[0] = range[1] = exp;
|
||||||
{
|
return true;
|
||||||
/* In an assignment involving a cast, ignore the type
|
|
||||||
of the cast and consider the type of its operand. */
|
|
||||||
tree_code code = gimple_assign_rhs_code (def);
|
|
||||||
if (code == NOP_EXPR)
|
|
||||||
op = gimple_assign_rhs1 (def);
|
|
||||||
}
|
}
|
||||||
else if (gimple_code (def) == GIMPLE_PHI)
|
|
||||||
|
wide_int min, max;
|
||||||
|
enum value_range_type range_type
|
||||||
|
= (TREE_CODE (exp) == SSA_NAME
|
||||||
|
? get_range_info (exp, &min, &max) : VR_VARYING);
|
||||||
|
|
||||||
|
if (range_type == VR_VARYING)
|
||||||
{
|
{
|
||||||
/* In a phi, a constant argument may be unsigned even
|
/* No range information available. */
|
||||||
if in the source it's signed and negative. Ignore
|
range[0] = NULL_TREE;
|
||||||
those and consider the result of a phi signed if
|
range[1] = NULL_TREE;
|
||||||
all its non-constant operands are. */
|
|
||||||
unsigned nargs = gimple_phi_num_args (def);
|
|
||||||
for (unsigned i = 0; i != nargs; ++i)
|
|
||||||
{
|
|
||||||
tree op = gimple_phi_arg_def (def, i);
|
|
||||||
if (TREE_CODE (op) != INTEGER_CST
|
|
||||||
&& !operand_signed_p (op))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
tree exptype = TREE_TYPE (exp);
|
||||||
|
unsigned expprec = TYPE_PRECISION (exptype);
|
||||||
|
wide_int wzero = wi::zero (expprec);
|
||||||
|
wide_int wmaxval = wide_int (TYPE_MAX_VALUE (exptype));
|
||||||
|
|
||||||
|
bool signed_p = !TYPE_UNSIGNED (exptype);
|
||||||
|
|
||||||
|
if (range_type == VR_ANTI_RANGE)
|
||||||
|
{
|
||||||
|
if (signed_p)
|
||||||
|
{
|
||||||
|
if (wi::les_p (max, wzero))
|
||||||
|
{
|
||||||
|
/* EXP is not in a strictly negative range. That means
|
||||||
|
it must be in some (not necessarily strictly) positive
|
||||||
|
range which includes zero. Since in signed to unsigned
|
||||||
|
conversions negative values end up converted to large
|
||||||
|
positive values, and otherwise they are not valid sizes,
|
||||||
|
the resulting range is in both cases [0, TYPE_MAX]. */
|
||||||
|
min = wzero;
|
||||||
|
max = wmaxval;
|
||||||
|
}
|
||||||
|
else if (wi::les_p (min - 1, wzero))
|
||||||
|
{
|
||||||
|
/* EXP is not in a negative-positive range. That means EXP
|
||||||
|
is either negative, or greater than max. Since negative
|
||||||
|
sizes are invalid make the range [MAX + 1, TYPE_MAX]. */
|
||||||
|
min = max + 1;
|
||||||
|
max = wmaxval;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
max = min - 1;
|
||||||
|
min = wzero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (wi::eq_p (wzero, min - 1))
|
||||||
|
{
|
||||||
|
/* EXP is unsigned and not in the range [1, MAX]. That means
|
||||||
|
it's either zero or greater than MAX. Even though 0 would
|
||||||
|
normally be detected by -Walloc-zero set the range to
|
||||||
|
[MAX, TYPE_MAX] so that when MAX is greater than the limit
|
||||||
|
the whole range is diagnosed. */
|
||||||
|
min = max + 1;
|
||||||
|
max = wmaxval;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
max = min - 1;
|
||||||
|
min = wzero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return !TYPE_UNSIGNED (TREE_TYPE (op));
|
range[0] = wide_int_to_tree (exptype, min);
|
||||||
|
range[1] = wide_int_to_tree (exptype, max);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Diagnose a call EXP to function FN decorated with attribute alloc_size
|
/* Diagnose a call EXP to function FN decorated with attribute alloc_size
|
||||||
|
@ -1316,8 +1368,8 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
|
||||||
if (tree_int_cst_lt (args[i], integer_zero_node))
|
if (tree_int_cst_lt (args[i], integer_zero_node))
|
||||||
{
|
{
|
||||||
warned = warning_at (loc, OPT_Walloc_size_larger_than_,
|
warned = warning_at (loc, OPT_Walloc_size_larger_than_,
|
||||||
"argument %i value %qE is negative",
|
"%Kargument %i value %qE is negative",
|
||||||
idx[i] + 1, args[i]);
|
exp, idx[i] + 1, args[i]);
|
||||||
}
|
}
|
||||||
else if (integer_zerop (args[i]))
|
else if (integer_zerop (args[i]))
|
||||||
{
|
{
|
||||||
|
@ -1334,8 +1386,8 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
|
||||||
&& !lookup_attribute ("returns_nonnull",
|
&& !lookup_attribute ("returns_nonnull",
|
||||||
TYPE_ATTRIBUTES (TREE_TYPE (fn)))))
|
TYPE_ATTRIBUTES (TREE_TYPE (fn)))))
|
||||||
warned = warning_at (loc, OPT_Walloc_zero,
|
warned = warning_at (loc, OPT_Walloc_zero,
|
||||||
"argument %i value is zero",
|
"%Kargument %i value is zero",
|
||||||
idx[i] + 1);
|
exp, idx[i] + 1);
|
||||||
}
|
}
|
||||||
else if (tree_int_cst_lt (maxobjsize, args[i]))
|
else if (tree_int_cst_lt (maxobjsize, args[i]))
|
||||||
{
|
{
|
||||||
|
@ -1351,79 +1403,31 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
warned = warning_at (loc, OPT_Walloc_size_larger_than_,
|
warned = warning_at (loc, OPT_Walloc_size_larger_than_,
|
||||||
"argument %i value %qE exceeds "
|
"%Kargument %i value %qE exceeds "
|
||||||
"maximum object size %E",
|
"maximum object size %E",
|
||||||
idx[i] + 1, args[i], maxobjsize);
|
exp, idx[i] + 1, args[i], maxobjsize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (TREE_CODE (args[i]) == SSA_NAME)
|
else if (TREE_CODE (args[i]) == SSA_NAME
|
||||||
|
&& get_size_range (args[i], argrange[i]))
|
||||||
{
|
{
|
||||||
tree type = TREE_TYPE (args[i]);
|
|
||||||
|
|
||||||
wide_int min, max;
|
|
||||||
value_range_type range_type = get_range_info (args[i], &min, &max);
|
|
||||||
if (range_type == VR_RANGE)
|
|
||||||
{
|
|
||||||
argrange[i][0] = wide_int_to_tree (type, min);
|
|
||||||
argrange[i][1] = wide_int_to_tree (type, max);
|
|
||||||
}
|
|
||||||
else if (range_type == VR_ANTI_RANGE)
|
|
||||||
{
|
|
||||||
/* For an anti-range, if the type of the formal argument
|
|
||||||
is unsigned and the bounds of the range are of opposite
|
|
||||||
signs when interpreted as signed, check to see if the
|
|
||||||
type of the actual argument is signed. If so, the lower
|
|
||||||
bound must be taken to be zero (rather than a large
|
|
||||||
positive value corresonding to the actual lower bound
|
|
||||||
interpreted as unsigned) and there is nothing else that
|
|
||||||
can be inferred from it. */
|
|
||||||
--min;
|
|
||||||
++max;
|
|
||||||
wide_int zero = wi::uhwi (0, TYPE_PRECISION (type));
|
|
||||||
if (TYPE_UNSIGNED (type)
|
|
||||||
&& wi::lts_p (zero, min) && wi::lts_p (max, zero)
|
|
||||||
&& operand_signed_p (args[i]))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
argrange[i][0] = wide_int_to_tree (type, max);
|
|
||||||
argrange[i][1] = wide_int_to_tree (type, min);
|
|
||||||
|
|
||||||
/* Verify that the anti-range doesn't make all arguments
|
|
||||||
invalid (treat the anti-range ~[0, 0] as invalid). */
|
|
||||||
if (tree_int_cst_lt (maxobjsize, argrange[i][0])
|
|
||||||
&& tree_int_cst_le (argrange[i][1], integer_zero_node))
|
|
||||||
{
|
|
||||||
warned
|
|
||||||
= warning_at (loc, OPT_Walloc_size_larger_than_,
|
|
||||||
(TYPE_UNSIGNED (type)
|
|
||||||
? G_("argument %i range [%E, %E] exceeds "
|
|
||||||
"maximum object size %E")
|
|
||||||
: G_("argument %i range [%E, %E] is both "
|
|
||||||
"negative and exceeds maximum object "
|
|
||||||
"size %E")),
|
|
||||||
idx[i] + 1, argrange[i][0],
|
|
||||||
argrange[i][1], maxobjsize);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Verify that the argument's range is not negative (including
|
/* Verify that the argument's range is not negative (including
|
||||||
upper bound of zero). */
|
upper bound of zero). */
|
||||||
if (tree_int_cst_lt (argrange[i][0], integer_zero_node)
|
if (tree_int_cst_lt (argrange[i][0], integer_zero_node)
|
||||||
&& tree_int_cst_le (argrange[i][1], integer_zero_node))
|
&& tree_int_cst_le (argrange[i][1], integer_zero_node))
|
||||||
{
|
{
|
||||||
warned = warning_at (loc, OPT_Walloc_size_larger_than_,
|
warned = warning_at (loc, OPT_Walloc_size_larger_than_,
|
||||||
"argument %i range [%E, %E] is negative",
|
"%Kargument %i range [%E, %E] is negative",
|
||||||
idx[i] + 1, argrange[i][0], argrange[i][1]);
|
exp, idx[i] + 1,
|
||||||
|
argrange[i][0], argrange[i][1]);
|
||||||
}
|
}
|
||||||
else if (tree_int_cst_lt (maxobjsize, argrange[i][0]))
|
else if (tree_int_cst_lt (maxobjsize, argrange[i][0]))
|
||||||
{
|
{
|
||||||
warned = warning_at (loc, OPT_Walloc_size_larger_than_,
|
warned = warning_at (loc, OPT_Walloc_size_larger_than_,
|
||||||
"argument %i range [%E, %E] exceeds "
|
"%Kargument %i range [%E, %E] exceeds "
|
||||||
"maximum object size %E",
|
"maximum object size %E",
|
||||||
idx[i] + 1, argrange[i][0], argrange[i][1],
|
exp, idx[i] + 1,
|
||||||
|
argrange[i][0], argrange[i][1],
|
||||||
maxobjsize);
|
maxobjsize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1450,15 +1454,15 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
|
||||||
|
|
||||||
if (vflow)
|
if (vflow)
|
||||||
warned = warning_at (loc, OPT_Walloc_size_larger_than_,
|
warned = warning_at (loc, OPT_Walloc_size_larger_than_,
|
||||||
"product %<%E * %E%> of arguments %i and %i "
|
"%Kproduct %<%E * %E%> of arguments %i and %i "
|
||||||
"exceeds %<SIZE_MAX%>",
|
"exceeds %<SIZE_MAX%>",
|
||||||
argrange[0][0], argrange[1][0],
|
exp, argrange[0][0], argrange[1][0],
|
||||||
idx[0] + 1, idx[1] + 1);
|
idx[0] + 1, idx[1] + 1);
|
||||||
else if (wi::ltu_p (wi::to_wide (maxobjsize, szprec), prod))
|
else if (wi::ltu_p (wi::to_wide (maxobjsize, szprec), prod))
|
||||||
warned = warning_at (loc, OPT_Walloc_size_larger_than_,
|
warned = warning_at (loc, OPT_Walloc_size_larger_than_,
|
||||||
"product %<%E * %E%> of arguments %i and %i "
|
"%Kproduct %<%E * %E%> of arguments %i and %i "
|
||||||
"exceeds maximum object size %E",
|
"exceeds maximum object size %E",
|
||||||
argrange[0][0], argrange[1][0],
|
exp, argrange[0][0], argrange[1][0],
|
||||||
idx[0] + 1, idx[1] + 1,
|
idx[0] + 1, idx[1] + 1,
|
||||||
maxobjsize);
|
maxobjsize);
|
||||||
|
|
||||||
|
|
|
@ -38,5 +38,6 @@ extern bool pass_by_reference (CUMULATIVE_ARGS *, machine_mode,
|
||||||
extern bool reference_callee_copied (CUMULATIVE_ARGS *, machine_mode,
|
extern bool reference_callee_copied (CUMULATIVE_ARGS *, machine_mode,
|
||||||
tree, bool);
|
tree, bool);
|
||||||
extern void maybe_warn_alloc_args_overflow (tree, tree, tree[2], int[2]);
|
extern void maybe_warn_alloc_args_overflow (tree, tree, tree[2], int[2]);
|
||||||
|
extern bool get_size_range (tree, tree[2]);
|
||||||
|
|
||||||
#endif // GCC_CALLS_H
|
#endif // GCC_CALLS_H
|
||||||
|
|
|
@ -1,3 +1,14 @@
|
||||||
|
2017-01-10 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR tree-optimization/78775
|
||||||
|
* gcc.dg/attr-alloc_size-4.c: Add test cases.
|
||||||
|
* gcc.dg/attr-alloc_size-10.c: New test.
|
||||||
|
* gcc.dg/attr-alloc_size-11.c: New test.
|
||||||
|
* gcc.dg/builtin-stringop-chk-7.c: New test.
|
||||||
|
* gcc.dg/pr78775.c: New test.
|
||||||
|
* gcc.dg/pr78973-2.c: New test.
|
||||||
|
* gcc.dg/pr78973.c: New test.
|
||||||
|
|
||||||
2017-01-10 Jeff Law <law@redhat.com>
|
2017-01-10 Jeff Law <law@redhat.com>
|
||||||
|
|
||||||
PR tree-optimization/77766
|
PR tree-optimization/77766
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
/* Verify that -Walloc-size-greater-than doesn't cause false positives
|
||||||
|
for anti-ranges. Note that not all of the statements used to create
|
||||||
|
anti-ranges below result in the argument being represented as an anti
|
||||||
|
range.
|
||||||
|
|
||||||
|
{ dg-do compile }
|
||||||
|
{ dg-options "-O2 -Walloc-size-larger-than=12" } */
|
||||||
|
|
||||||
|
#define SCHAR_MAX __SCHAR_MAX__
|
||||||
|
#define SCHAR_MIN (-SCHAR_MAX - 1)
|
||||||
|
#define UCHAR_MAX (SCHAR_MAX * 2 + 1)
|
||||||
|
|
||||||
|
#define SHRT_MAX __SHRT_MAX__
|
||||||
|
#define SHRT_MIN (-SHRT_MAX - 1)
|
||||||
|
#define USHRT_MAX (SHRT_MAX * 2 + 1)
|
||||||
|
|
||||||
|
#define INT_MAX __INT_MAX__
|
||||||
|
#define INT_MIN (-INT_MAX - 1)
|
||||||
|
#define UINT_MAX (INT_MAX * 2U + 1)
|
||||||
|
|
||||||
|
#define LONG_MAX __LONG_MAX__
|
||||||
|
#define LONG_MIN (-LONG_MAX - 1)
|
||||||
|
#define ULONG_MAX (LONG_MAX * 2LU + 1)
|
||||||
|
|
||||||
|
#define PTRDIFF_MAX __PTRDIFF_MAX__
|
||||||
|
#define PTRDIFF_MIN (-PTRDIFF_MAX - 1)
|
||||||
|
#define SIZE_MAX __SIZE_MAX__
|
||||||
|
|
||||||
|
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||||
|
typedef __SIZE_TYPE__ size_t;
|
||||||
|
|
||||||
|
#define CONCAT(a, b) a ## b
|
||||||
|
#define CAT(a, b) CONCAT (a, b)
|
||||||
|
|
||||||
|
/* Macro to generate a unique function to test the anti-range
|
||||||
|
~[MIN, MAX] for type T. */
|
||||||
|
#define TEST(T, min, max) \
|
||||||
|
void* CAT (test_anti_range_, __LINE__)(T n) \
|
||||||
|
{ \
|
||||||
|
extern void* CAT (alloc_anti_range_, __LINE__)(T) \
|
||||||
|
__attribute__ ((alloc_size (1))); \
|
||||||
|
if (min <= n && n <= max) \
|
||||||
|
n = min - 1; \
|
||||||
|
return CAT (alloc_anti_range_, __LINE__)(n); \
|
||||||
|
} typedef void dummy /* Require a semicolon. */
|
||||||
|
|
||||||
|
|
||||||
|
/* Verify the anti-range ~[TYPE_MAX - 1, TYPE_MAX - 1]. */
|
||||||
|
TEST (signed char, SCHAR_MAX - 1, SCHAR_MAX - 1);
|
||||||
|
TEST (unsigned char, UCHAR_MAX - 1, UCHAR_MAX - 1);
|
||||||
|
TEST (short, SHRT_MAX - 1, SHRT_MAX - 1);
|
||||||
|
TEST (unsigned short, USHRT_MAX - 1, USHRT_MAX - 1);
|
||||||
|
TEST (int, INT_MAX - 1, INT_MAX - 1);
|
||||||
|
TEST (unsigned, UINT_MAX - 1, UINT_MAX - 1);
|
||||||
|
TEST (long, LONG_MAX - 1, LONG_MAX - 1);
|
||||||
|
TEST (unsigned long, ULONG_MAX - 1, ULONG_MAX - 1);
|
||||||
|
TEST (ptrdiff_t, PTRDIFF_MAX - 1, PTRDIFF_MAX - 1);
|
||||||
|
TEST (size_t, SIZE_MAX - 1, SIZE_MAX - 1);
|
||||||
|
|
||||||
|
/* Verify ~[0, 0]. */
|
||||||
|
TEST (signed char, 0, 0);
|
||||||
|
TEST (unsigned char, 0, 0);
|
||||||
|
TEST (short, 0, 0);
|
||||||
|
TEST (unsigned short, 0, 0);
|
||||||
|
TEST (int, 0, 0);
|
||||||
|
TEST (unsigned, 0, 0);
|
||||||
|
TEST (long, 0, 0);
|
||||||
|
TEST (unsigned long, 0, 0);
|
||||||
|
TEST (ptrdiff_t, 0, 0);
|
||||||
|
TEST (size_t, 0, 0);
|
||||||
|
|
||||||
|
/* Verify ~[1, 1]. */
|
||||||
|
TEST (signed char, 1, 1);
|
||||||
|
TEST (unsigned char, 1, 1);
|
||||||
|
TEST (short, 1, 1);
|
||||||
|
TEST (unsigned short, 1, 1);
|
||||||
|
TEST (int, 1, 1);
|
||||||
|
TEST (unsigned, 1, 1);
|
||||||
|
TEST (long, 1, 1);
|
||||||
|
TEST (unsigned long, 1, 1);
|
||||||
|
TEST (ptrdiff_t, 1, 1);
|
||||||
|
TEST (size_t, 1, 1);
|
||||||
|
|
||||||
|
|
||||||
|
/* Verify ~[TYPE_MAX - 2, TYPE_MAX - 1]. */
|
||||||
|
TEST (signed char, SCHAR_MAX - 2, SCHAR_MAX - 1);
|
||||||
|
TEST (unsigned char, UCHAR_MAX - 2, UCHAR_MAX - 1);
|
||||||
|
TEST (short, SHRT_MAX - 2, SHRT_MAX - 1);
|
||||||
|
TEST (unsigned short, USHRT_MAX - 2, USHRT_MAX - 1);
|
||||||
|
TEST (int, INT_MAX - 2, INT_MAX - 1);
|
||||||
|
TEST (unsigned, UINT_MAX - 2, UINT_MAX - 1);
|
||||||
|
TEST (long, LONG_MAX - 2, LONG_MAX - 1);
|
||||||
|
TEST (unsigned long, ULONG_MAX - 2, ULONG_MAX - 1);
|
||||||
|
TEST (ptrdiff_t, PTRDIFF_MAX - 2, PTRDIFF_MAX - 1);
|
||||||
|
TEST (size_t, SIZE_MAX - 2, SIZE_MAX - 1);
|
||||||
|
|
||||||
|
/* Verify ~[0, 2]. */
|
||||||
|
TEST (signed char, 0, 2);
|
||||||
|
TEST (unsigned char, 0, 2);
|
||||||
|
TEST (short, 0, 2);
|
||||||
|
TEST (unsigned short, 0, 2);
|
||||||
|
TEST (int, 0, 2);
|
||||||
|
TEST (unsigned int, 0, 2);
|
||||||
|
TEST (long, 0, 2);
|
||||||
|
TEST (unsigned long, 0, 2);
|
||||||
|
TEST (ptrdiff_t, 0, 2);
|
||||||
|
TEST (size_t, 0, 2);
|
||||||
|
|
||||||
|
/* Verify the signed anti-range ~[TYPE_MIN - 2, -1]. */
|
||||||
|
TEST (signed char, SCHAR_MIN + 2, -1);
|
||||||
|
TEST (short, SHRT_MIN + 2, -1);
|
||||||
|
TEST (int, INT_MIN + 2, -1);
|
||||||
|
TEST (long, LONG_MIN + 2, -1);
|
||||||
|
TEST (ptrdiff_t, PTRDIFF_MIN + 2, -1);
|
||||||
|
|
||||||
|
/* Verify the signed anti-range ~[TYPE_MIN - 2, 0]. */
|
||||||
|
TEST (signed char, SCHAR_MIN + 2, 0);
|
||||||
|
TEST (short, SHRT_MIN + 2, 0);
|
||||||
|
TEST (int, INT_MIN + 2, 0);
|
||||||
|
TEST (long, LONG_MIN + 2, 0);
|
||||||
|
TEST (ptrdiff_t, PTRDIFF_MIN + 2, 0);
|
||||||
|
|
||||||
|
/* Verify the signed anti-range ~[TYPE_MIN - 2, 1]. */
|
||||||
|
TEST (signed char, SCHAR_MIN + 2, 1);
|
||||||
|
TEST (short, SHRT_MIN + 2, 1);
|
||||||
|
TEST (int, INT_MIN + 2, 1);
|
||||||
|
TEST (long, LONG_MIN + 2, 1);
|
||||||
|
TEST (ptrdiff_t, PTRDIFF_MIN + 2, 1);
|
||||||
|
|
||||||
|
/* Verify the signed anti-range ~[TYPE_MIN - 2, 2]. */
|
||||||
|
TEST (signed char, SCHAR_MIN + 2, 2);
|
||||||
|
TEST (short, SHRT_MIN + 2, 2);
|
||||||
|
TEST (int, INT_MIN + 2, 2);
|
||||||
|
TEST (long, LONG_MIN + 2, 2);
|
||||||
|
TEST (ptrdiff_t, PTRDIFF_MIN + 2, 2);
|
||||||
|
|
||||||
|
/* Verify the signed anti-range ~[-1, 2]. */
|
||||||
|
TEST (signed char, -1, 2);
|
||||||
|
TEST (short, -1, 2);
|
||||||
|
TEST (int, -1, 2);
|
||||||
|
TEST (long, -1, 2);
|
||||||
|
TEST (ptrdiff_t, 01, 2);
|
|
@ -0,0 +1,69 @@
|
||||||
|
/* Verify that -Walloc-size-greater-than doesn't cause false positives
|
||||||
|
for anti-ranges. Note that not all of the statements below result
|
||||||
|
in the argument being represented as an anti-range.
|
||||||
|
|
||||||
|
{ dg-do compile }
|
||||||
|
{ dg-options "-O2 -Walloc-size-larger-than=12 -ftrack-macro-expansion=0" } */
|
||||||
|
|
||||||
|
#define SCHAR_MAX __SCHAR_MAX__
|
||||||
|
#define SCHAR_MIN (-SCHAR_MAX - 1)
|
||||||
|
#define UCHAR_MAX (SCHAR_MAX * 2 + 1)
|
||||||
|
|
||||||
|
#define SHRT_MAX __SHRT_MAX__
|
||||||
|
#define SHRT_MIN (-SHRT_MAX - 1)
|
||||||
|
#define USHRT_MAX (SHRT_MAX * 2 + 1)
|
||||||
|
|
||||||
|
#define INT_MAX __INT_MAX__
|
||||||
|
#define INT_MIN (-INT_MAX - 1)
|
||||||
|
#define UINT_MAX (INT_MAX * 2U + 1)
|
||||||
|
|
||||||
|
#define LONG_MAX __LONG_MAX__
|
||||||
|
#define LONG_MIN (-LONG_MAX - 1)
|
||||||
|
#define ULONG_MAX (LONG_MAX * 2LU + 1)
|
||||||
|
|
||||||
|
#define PTRDIFF_MAX __PTRDIFF_MAX__
|
||||||
|
#define PTRDIFF_MIN (-PTRDIFF_MAX - 1)
|
||||||
|
#define SIZE_MAX __SIZE_MAX__
|
||||||
|
|
||||||
|
#define ALLOC_MAX 12
|
||||||
|
|
||||||
|
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||||
|
typedef __SIZE_TYPE__ size_t;
|
||||||
|
|
||||||
|
#define CONCAT(a, b) a ## b
|
||||||
|
#define CAT(a, b) CONCAT (a, b)
|
||||||
|
|
||||||
|
/* Macro to generate a unique function to test the anti-range
|
||||||
|
~[MIN, MAX] for type T. */
|
||||||
|
#define TEST(T, min, max) \
|
||||||
|
void* CAT (test_anti_range_, __LINE__)(T n) \
|
||||||
|
{ \
|
||||||
|
extern void* CAT (alloc_anti_range_, __LINE__)(T) \
|
||||||
|
__attribute__ ((alloc_size (1))); \
|
||||||
|
if (min <= n && n <= max) \
|
||||||
|
n = min - 1; \
|
||||||
|
return CAT (alloc_anti_range_, __LINE__)(n); \
|
||||||
|
} typedef void dummy /* Require a semicolon. */
|
||||||
|
|
||||||
|
/* The following tests fail because of missing range information. */
|
||||||
|
TEST (signed char, SCHAR_MIN + 2, ALLOC_MAX); /* { dg-warning "argument 1 range \\\[13, \[0-9\]+\\\] exceeds maximum object size 12" "missing range info for signed char" { xfail *-*-* } } */
|
||||||
|
TEST (short, SHRT_MIN + 2, ALLOC_MAX); /* { dg-warning "argument 1 range \\\[13, \[0-9\]+\\\] exceeds maximum object size 12" "missing range info for short" { xfail *-*-* } } */
|
||||||
|
|
||||||
|
TEST (int, INT_MIN + 2, ALLOC_MAX); /* { dg-warning "argument 1 range \\\[13, \[0-9\]+\\\] exceeds maximum object size 12" } */
|
||||||
|
TEST (int, -3, ALLOC_MAX); /* { dg-warning "argument 1 range \\\[13, \[0-9\]+\\\] exceeds maximum object size 12" } */
|
||||||
|
TEST (int, -2, ALLOC_MAX); /* { dg-warning "argument 1 range \\\[13, \[0-9\]+\\\] exceeds maximum object size 12" } */
|
||||||
|
TEST (int, -1, ALLOC_MAX); /* { dg-warning "argument 1 range \\\[13, \[0-9\]+\\\] exceeds maximum object size 12" } */
|
||||||
|
TEST (int, 0, ALLOC_MAX); /* { dg-warning "argument 1 range \\\[13, \[0-9\]+\\\] exceeds maximum object size 12" } */
|
||||||
|
TEST (int, 1, ALLOC_MAX); /* { dg-warning "argument 1 range \\\[13, \[0-9\]+\\\] exceeds maximum object size 12" } */
|
||||||
|
TEST (int, 1, INT_MAX - 1); /* { dg-warning "argument 1 range \\\[\[0-9\]+, \[0-9\]+\\\] exceeds maximum object size 12" } */
|
||||||
|
|
||||||
|
/* The following two aren't necessarily anti-ranges. */
|
||||||
|
TEST (int, 1, INT_MAX); /* { dg-warning "argument 1 range \\\[-\[0-9\]+, 0\\\] is negative" } */
|
||||||
|
TEST (int, 0, INT_MAX); /* { dg-warning "argument 1 range \\\[-\[0-9\]+, -1\\\] is negative" } */
|
||||||
|
|
||||||
|
TEST (long, LONG_MIN + 2, ALLOC_MAX); /* { dg-warning "argument 1 range \\\[13, \[0-9\]+\\\] exceeds maximum object size 12" } */
|
||||||
|
TEST (ptrdiff_t, PTRDIFF_MIN + 2, ALLOC_MAX); /* { dg-warning "argument 1 range \\\[13, \[0-9\]+\\\] exceeds maximum object size 12" } */
|
||||||
|
|
||||||
|
TEST (unsigned, 0, ALLOC_MAX); /* { dg-warning "argument 1 range \\\[13, \[0-9\]+\\\] exceeds maximum object size 12" } */
|
||||||
|
TEST (unsigned long, 0, ALLOC_MAX); /* { dg-warning "argument 1 range \\\[13, \[0-9\]+\\\] exceeds maximum object size 12" } */
|
||||||
|
TEST (size_t, 0, ALLOC_MAX); /* { dg-warning "argument 1 range \\\[13, \[0-9\]+\\\] exceeds maximum object size 12" } */
|
|
@ -128,15 +128,22 @@ test_int_range (int n)
|
||||||
|
|
||||||
sink (f_int_1 (SR (min, 1234)));
|
sink (f_int_1 (SR (min, 1234)));
|
||||||
sink (f_int_1 (SR (-2, -1))); /* { dg-warning "argument 1 range \\\[-2, -1\\\] is negative" } */
|
sink (f_int_1 (SR (-2, -1))); /* { dg-warning "argument 1 range \\\[-2, -1\\\] is negative" } */
|
||||||
|
|
||||||
sink (f_int_1 (SR (1235, 2345))); /* { dg-warning "argument 1 range \\\[1235, 2345\\\] exceeds maximum object size 1234" } */
|
sink (f_int_1 (SR (1235, 2345))); /* { dg-warning "argument 1 range \\\[1235, 2345\\\] exceeds maximum object size 1234" } */
|
||||||
sink (f_int_1 (SR (max - 1, max))); /* { dg-warning "argument 1 range \\\[\[0-9\]+, \[0-9\]+\\\] exceeds maximum object size 1234" } */
|
sink (f_int_1 (SR (max - 1, max))); /* { dg-warning "argument 1 range \\\[\[0-9\]+, \[0-9\]+\\\] exceeds maximum object size 1234" } */
|
||||||
|
|
||||||
sink (f_int_1 (SAR (-1, 1)));
|
sink (f_int_1 (SAR (-1, 1)));
|
||||||
sink (f_int_1 (SAR (-2, 12)));
|
sink (f_int_1 (SAR (-2, 12)));
|
||||||
sink (f_int_1 (SAR (-3, 123)));
|
sink (f_int_1 (SAR (-3, 123)));
|
||||||
sink (f_int_1 (SAR (-4, 1234))); /* { dg-warning "argument 1 range \\\[1235, -5\\\] is both negative and exceeds maximum object size 1234" } */
|
sink (f_int_1 (SAR (-4, 1234))); /* { dg-warning "argument 1 range \\\[1235, \[0-9\]+\\\] exceeds maximum object size 1234" } */
|
||||||
sink (f_int_1 (SAR (min + 1, 1233)));
|
sink (f_int_1 (SAR (min + 1, 1233)));
|
||||||
sink (f_int_1 (SAR (min + 2, 1235))); /* { dg-warning "argument 1 range \\\[1236, -\[0-9\]+\\\] is both negative and exceeds maximum object size 1234" } */
|
sink (f_int_1 (SAR (min + 2, 1235))); /* { dg-warning "argument 1 range \\\[1236, \[0-9\]+\\\] exceeds maximum object size 1234" } */
|
||||||
|
sink (f_int_1 (SAR (0, max))); /* { dg-warning "argument 1 range \\\[-\[0-9\]*, -1\\\] is negative" } */
|
||||||
|
/* The range below includes zero which would be diagnosed by
|
||||||
|
-Walloc-size-zero but since all other values are negative it
|
||||||
|
is diagnosed by -Walloc-size-larger-than. */
|
||||||
|
sink (f_int_1 (SAR (1, max))); /* { dg-warning "argument 1 range \\\[-\[0-9\]*, 0\\\] is negative" } */
|
||||||
|
sink (f_int_1 (SAR (2, max)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
/* Verify that -Wstringop-overflow doesn't cause false positives for
|
||||||
|
anti-ranges. Note that not all of the statements below result in
|
||||||
|
the memset argument being represented as an anti-range.
|
||||||
|
|
||||||
|
{ dg-do compile }
|
||||||
|
{ dg-options "-O2 -Wstringop-overflow" } */
|
||||||
|
|
||||||
|
#define SCHAR_MAX __SCHAR_MAX__
|
||||||
|
#define UCHAR_MAX (SCHAR_MAX * 2 + 1)
|
||||||
|
|
||||||
|
#define SHRT_MAX __SHRT_MAX__
|
||||||
|
#define USHRT_MAX (SHRT_MAX * 2 + 1)
|
||||||
|
|
||||||
|
#define INT_MAX __INT_MAX__
|
||||||
|
#define UINT_MAX (INT_MAX * 2U + 1)
|
||||||
|
|
||||||
|
#define LONG_MAX __LONG_MAX__
|
||||||
|
#define ULONG_MAX (LONG_MAX * 2LU + 1)
|
||||||
|
|
||||||
|
#define PTRDIFF_MAX __PTRDIFF_MAX__
|
||||||
|
#define SIZE_MAX __SIZE_MAX__
|
||||||
|
|
||||||
|
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||||
|
typedef __SIZE_TYPE__ size_t;
|
||||||
|
|
||||||
|
#define TEST_AR_1(T, prefix) \
|
||||||
|
void test_ar_1_ ## prefix (void *d, T n) \
|
||||||
|
{ \
|
||||||
|
if (n == prefix ## _MAX - 1) \
|
||||||
|
n = prefix ## _MAX - 2; \
|
||||||
|
__builtin_memset (d, 0, n); \
|
||||||
|
} typedef void dummy
|
||||||
|
|
||||||
|
#define TEST_AR_2(T, prefix) \
|
||||||
|
void test_ar_2_ ## prefix (void *d, T n) \
|
||||||
|
{ \
|
||||||
|
if (prefix ## _MAX - 2 <= n && n <= prefix ## _MAX - 1) \
|
||||||
|
n = prefix ## _MAX - 3; \
|
||||||
|
__builtin_memset (d, 0, n); \
|
||||||
|
} typedef void dummy
|
||||||
|
|
||||||
|
/* Verify antirange where MIN == MAX. */
|
||||||
|
TEST_AR_1 (signed char, SCHAR);
|
||||||
|
TEST_AR_1 (unsigned char, UCHAR);
|
||||||
|
|
||||||
|
TEST_AR_1 (short, SHRT);
|
||||||
|
TEST_AR_1 (unsigned short, USHRT);
|
||||||
|
|
||||||
|
TEST_AR_1 (int, INT);
|
||||||
|
TEST_AR_1 (unsigned, UINT);
|
||||||
|
|
||||||
|
TEST_AR_1 (long, LONG);
|
||||||
|
TEST_AR_1 (unsigned long, ULONG);
|
||||||
|
|
||||||
|
TEST_AR_1 (ptrdiff_t, PTRDIFF);
|
||||||
|
TEST_AR_1 (size_t, SIZE);
|
||||||
|
|
||||||
|
/* Verify antirange where MIN < MAX. */
|
||||||
|
TEST_AR_2 (signed char, SCHAR);
|
||||||
|
TEST_AR_2 (unsigned char, UCHAR);
|
||||||
|
|
||||||
|
TEST_AR_2 (short, SHRT);
|
||||||
|
TEST_AR_2 (unsigned short, USHRT);
|
||||||
|
|
||||||
|
TEST_AR_2 (int, INT);
|
||||||
|
TEST_AR_2 (unsigned, UINT);
|
||||||
|
|
||||||
|
TEST_AR_2 (long, LONG);
|
||||||
|
TEST_AR_2 (unsigned long, ULONG);
|
||||||
|
|
||||||
|
TEST_AR_2 (ptrdiff_t, PTRDIFF);
|
||||||
|
TEST_AR_2 (size_t, SIZE);
|
|
@ -0,0 +1,19 @@
|
||||||
|
/* PR c/78775 - [7 Regression] ICE in maybe_warn_alloc_args_overflow
|
||||||
|
{ dg-do compile }
|
||||||
|
{ dg-options "-O2" } */
|
||||||
|
|
||||||
|
int a, b, *c;
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
unsigned long d = 0;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
switch (b)
|
||||||
|
case 'S':
|
||||||
|
d = a;
|
||||||
|
c = __builtin_malloc (d);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* PR c/78973 - warning: ‘memcpy’: specified size exceeds maximum object
|
||||||
|
size [-Wstringop-overflow=]
|
||||||
|
|
||||||
|
This is a companion test for the bug above that verifies that the correct
|
||||||
|
range of the int variable is detected.
|
||||||
|
|
||||||
|
{ dg-do compile }
|
||||||
|
{ dg-require-effective-target int32plus }
|
||||||
|
{ dg-options "-O2 -Walloc-size-larger-than=4" } */
|
||||||
|
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
void f (int n)
|
||||||
|
{
|
||||||
|
if (n <= 4)
|
||||||
|
p = __builtin_malloc (n);
|
||||||
|
/* { dg-warning "argument 1 range \\\[\[0-9\]+, \[0-9\]+\\\] exceeds maximum object size 4" "ilp32" { xfail { ! lp64 } } .-1 } */
|
||||||
|
}
|
||||||
|
|
||||||
|
void g (unsigned n)
|
||||||
|
{
|
||||||
|
if (n < 5)
|
||||||
|
n = 5;
|
||||||
|
f (n);
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
/* PR c/78973 - warning: ‘memcpy’: specified size exceeds maximum object size
|
||||||
|
|
||||||
|
Test case for what was initially thought to be a false positive but after
|
||||||
|
deeper investigation turned out to be a true positive.
|
||||||
|
|
||||||
|
{ dg-do compile }
|
||||||
|
{ dg-options "-O2 -Wall" } */
|
||||||
|
|
||||||
|
void f (void *p, int n)
|
||||||
|
{
|
||||||
|
if (n <= 4)
|
||||||
|
__builtin_memset (p, 0, n); /* { dg-warning "exceeds maximum object size" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
void g (void *d, unsigned n)
|
||||||
|
{
|
||||||
|
if (n < 5)
|
||||||
|
n = 5;
|
||||||
|
f (d, n);
|
||||||
|
}
|
Loading…
Reference in New Issue