Commit c16880ef by Martin Sebor Committed by Martin Sebor

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
parent 5d582919
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>
* 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;
}
/* 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
manipulation function given by EXP are within valid bounds and that
the operation does not lead to buffer overflow. Arguments other than
......
......@@ -38,5 +38,6 @@ extern bool pass_by_reference (CUMULATIVE_ARGS *, machine_mode,
extern bool reference_callee_copied (CUMULATIVE_ARGS *, machine_mode,
tree, bool);
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
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>
PR tree-optimization/77766
......
/* 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);
/* 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 (-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 (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 (-2, 12)));
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 + 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
......
/* 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);
/* 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;
}
/* 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);
}
/* 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment