Commit 8bd9f164 by Martin Sebor Committed by Martin Sebor

PR c/77531 - __attribute__((alloc_size(1,2))) could also warn on multiplication overflow

PR c/77531 - __attribute__((alloc_size(1,2))) could also warn on multiplication overflow
PR c/78284 - warn on malloc with very large arguments

gcc/c-family/ChangeLog:

	PR c/78284
	* c.opt (-Walloc-zero, -Walloc-size-larger-than): New options.

gcc/ChangeLog:

	PR c/78284
	* builtin-attrs.def (ATTR_ALLOC_SIZE, ATTR_RETURNS_NONNULL): New
	identifier tree nodes.
	(ATTR_ALLOCA_SIZE_1_NOTHROW_LEAF_LIST): New attribute list.
	(ATTR_MALLOC_SIZE_1_NOTHROW_LIST): Same.
	(ATTR_MALLOC_SIZE_1_NOTHROW_LEAF_LIST): Same.
	(ATTR_MALLOC_SIZE_1_2_NOTHROW_LEAF_LIST): Same.
	(ATTR_ALLOC_SIZE_2_NOTHROW_LEAF_LIST): Same.
	* builtins.c (expand_builtin_alloca): Call
	maybe_warn_alloc_args_overflow.
	* builtins.def (aligned_alloc, calloc, malloc, realloc):
	Add attribute alloc_size.
	(alloca): Add attribute alloc_size and returns_nonnull.
	* calls.h (maybe_warn_alloc_args_overflow): Declare.
	* calls.c (alloc_max_size, operand_signed_p): New functions.
	(maybe_warn_alloc_args_overflow): Define.
	(initialize_argument_information): Diagnose overflow in functions
	declared with attaribute alloc_size.
	* doc/invoke.texi (Warning Options): Document -Walloc-zero and
	-Walloc-size-larger-than.

gcc/testsuite/ChangeLog:

	PR c/78284
	* gcc.dg/attr-alloc_size-3.c: New test.
	* gcc.dg/attr-alloc_size-4.c: New test.
	* gcc.dg/attr-alloc_size-5.c: New test.
	* gcc.dg/attr-alloc_size-6.c: New test.
	* gcc.dg/attr-alloc_size-7.c: New test.
	* gcc.dg/attr-alloc_size-8.c: New test.
	* gcc.dg/attr-alloc_size-9.c: New test.
	* gcc/testsuite/gcc.dg/errno-1.c: Adjust.

From-SVN: r243470
parent 410aa898
2016-12-08 Martin Sebor <msebor@redhat.com>
PR c/78284
* builtin-attrs.def (ATTR_ALLOC_SIZE, ATTR_RETURNS_NONNULL): New
identifier tree nodes.
(ATTR_ALLOCA_SIZE_1_NOTHROW_LEAF_LIST): New attribute list.
(ATTR_MALLOC_SIZE_1_NOTHROW_LIST): Same.
(ATTR_MALLOC_SIZE_1_NOTHROW_LEAF_LIST): Same.
(ATTR_MALLOC_SIZE_1_2_NOTHROW_LEAF_LIST): Same.
(ATTR_ALLOC_SIZE_2_NOTHROW_LEAF_LIST): Same.
* builtins.c (expand_builtin_alloca): Call
maybe_warn_alloc_args_overflow.
* builtins.def (aligned_alloc, calloc, malloc, realloc):
Add attribute alloc_size.
(alloca): Add attribute alloc_size and returns_nonnull.
* calls.h (maybe_warn_alloc_args_overflow): Declare.
* calls.c (alloc_max_size, operand_signed_p): New functions.
(maybe_warn_alloc_args_overflow): Define.
(initialize_argument_information): Diagnose overflow in functions
declared with attaribute alloc_size.
* doc/invoke.texi (Warning Options): Document -Walloc-zero and
-Walloc-size-larger-than.
2016-12-08 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-optimization/78671
......@@ -4797,12 +4797,12 @@ expand_builtin_alloca (tree exp, bool cannot_accumulate)
{
rtx op0;
rtx result;
bool valid_arglist;
unsigned int align;
bool alloca_with_align = (DECL_FUNCTION_CODE (get_callee_fndecl (exp))
tree fndecl = get_callee_fndecl (exp);
bool alloca_with_align = (DECL_FUNCTION_CODE (fndecl)
== BUILT_IN_ALLOCA_WITH_ALIGN);
valid_arglist
bool valid_arglist
= (alloca_with_align
? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
: validate_arglist (exp, INTEGER_TYPE, VOID_TYPE));
......@@ -4810,6 +4810,18 @@ expand_builtin_alloca (tree exp, bool cannot_accumulate)
if (!valid_arglist)
return NULL_RTX;
if ((alloca_with_align && !warn_vla_limit)
|| (!alloca_with_align && !warn_alloca_limit))
{
/* -Walloca-larger-than and -Wvla-larger-than settings override
the more general -Walloc-size-larger-than so unless either of
the former options is specified check the alloca arguments for
overflow. */
tree args[] = { CALL_EXPR_ARG (exp, 0), NULL_TREE };
int idx[] = { 0, -1 };
maybe_warn_alloc_args_overflow (fndecl, exp, args, idx);
}
/* Compute the argument. */
op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
......
2016-12-08 Martin Sebor <msebor@redhat.com>
PR c/78284
* c.opt (-Walloc-zero, -Walloc-size-larger-than): New options.
2016-12-08 Martin Sebor <msebor@redhat.com>
PR c/78165
* c-pretty-print (pp_c_integer_constant): Avoid formatting type
suffix.
......
......@@ -303,6 +303,15 @@ Walloca
C ObjC C++ ObjC++ Var(warn_alloca) Warning
Warn on any use of alloca.
Walloc-size-larger-than=
C ObjC C++ ObjC++ Var(warn_alloc_size_limit) Warning Joined
-Walloc-size-larger-than=<bytes> Warn for calls to allocation functions that
attempt to allocate objects larger than the specified number of bytes.
Walloc-zero
C ObjC C++ ObjC++ Var(warn_alloc_zero) Warning
-Walloc-zero Warn for calls to allocation functions that specify zero bytes.
Walloca-larger-than=
C ObjC C++ ObjC++ Var(warn_alloca_limit) Warning Joined RejectNegative UInteger
-Walloca-larger-than=<number> Warn on unbounded uses of
......
......@@ -37,7 +37,6 @@ extern bool pass_by_reference (CUMULATIVE_ARGS *, machine_mode,
tree, bool);
extern bool reference_callee_copied (CUMULATIVE_ARGS *, machine_mode,
tree, bool);
extern void maybe_warn_alloc_args_overflow (tree, tree, tree[2], int[2]);
#endif // GCC_CALLS_H
......@@ -257,6 +257,7 @@ Objective-C and Objective-C++ Dialects}.
@gccoptlist{-fsyntax-only -fmax-errors=@var{n} -Wpedantic @gol
-pedantic-errors @gol
-w -Wextra -Wall -Waddress -Waggregate-return @gol
-Walloc-zero -Walloc-size-larger-than=@var{n}
-Walloca -Walloca-larger-than=@var{n} @gol
-Wno-aggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol
-Wno-attributes -Wbool-compare -Wbool-operation @gol
......@@ -5099,6 +5100,27 @@ annotations.
Warn about overriding virtual functions that are not marked with the override
keyword.
@item -Walloc-zero
@opindex Wno-alloc-zero
@opindex Walloc-zero
Warn about calls to allocation functions decorated with attribute
@code{alloc_size} that specify zero bytes, including those to the built-in
forms of the functions @code{aligned_alloc}, @code{alloca}, @code{calloc},
@code{malloc}, and @code{realloc}. Because the behavior of these functions
when called with a zero size differs among implementations (and in the case
of @code{realloc} has been deprecated) relying on it may result in subtle
portability bugs and should be avoided.
@item -Walloc-size-larger-than=@var{n}
Warn about calls to functions decorated with attribute @code{alloc_size}
that attempt to allocate objects larger than the specified number of bytes,
or where the result of the size computation in an integer type with infinite
precision would exceed @code{SIZE_MAX / 2}. The option argument @var{n}
may end in one of the standard suffixes designating a multiple of bytes
such as @code{kB} and @code{KiB} for kilobyte and kibibyte, respectively,
@code{MB} and @code{MiB} for magabyte and mebibyte, and so on.
@xref{Function Attributes}.
@item -Walloca
@opindex Wno-alloca
@opindex Walloca
......
2016-12-08 Martin Sebor <msebor@redhat.com>
PR c/78284
* gcc.dg/attr-alloc_size-3.c: New test.
* gcc.dg/attr-alloc_size-4.c: New test.
* gcc.dg/attr-alloc_size-5.c: New test.
* gcc.dg/attr-alloc_size-6.c: New test.
* gcc.dg/attr-alloc_size-7.c: New test.
* gcc.dg/attr-alloc_size-8.c: New test.
* gcc.dg/attr-alloc_size-9.c: New test.
* gcc/testsuite/gcc.dg/errno-1.c: Adjust.
2016-12-08 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/65173
......
/* PR c/77531 - __attribute__((alloc_size(1,2))) could also warn on
multiplication overflow
PR c/78284 - warn on malloc with very large arguments
Test exercising the ability to detect and diagnose calls to allocation
functions decorated with attribute alloc_size that either overflow or
exceed the maximum object size specified by -Walloc-size-larger-than. */
/* { dg-do compile } */
/* { dg-options "-O2 -Wall -Walloc-size-larger-than=1234" } */
#define INT_MAX __INT_MAX__
#define INT_MIN (-INT_MAX - 1)
#define UINT_MAX (INT_MAX * 2U + 1)
#define SIZE_MAX __SIZE_MAX__
typedef __SIZE_TYPE__ size_t;
#define ALLOC_SIZE(...) __attribute__ ((alloc_size (__VA_ARGS__)))
void* f_uint_1 (unsigned) ALLOC_SIZE (1);
void* f_uint_2 (unsigned, unsigned) ALLOC_SIZE (1, 2);
void* f_int_1 (int) ALLOC_SIZE (1);
void* f_int_2 (int, int) ALLOC_SIZE (1, 2);
void* f_size_1 (size_t) ALLOC_SIZE (1);
void* f_size_2 (size_t, size_t) ALLOC_SIZE (1, 2);
size_t
unsigned_range (size_t min, size_t max)
{
extern size_t random_unsigned_value (void);
size_t val = random_unsigned_value ();
if (val < min || max < val) val = min;
return val;
}
int
signed_range (int min, int max)
{
extern int random_signed_value (void);
int val = random_signed_value ();
if (val < min || max < val) val = min;
return val;
}
size_t
unsigned_anti_range (size_t min, size_t max)
{
extern size_t random_unsigned_value (void);
size_t val = random_unsigned_value ();
if (min <= val && val <= max)
val = min - 1;
return val;
}
int
signed_anti_range (int min, int max)
{
extern int random_signed_value (void);
int val = random_signed_value ();
if (min <= val && val <= max)
val = min - 1;
return val;
}
#define UR(min, max) unsigned_range (min, max)
#define SR(min, max) signed_range (min, max)
#define UAR(min, max) unsigned_anti_range (min, max)
#define SAR(min, max) signed_anti_range (min, max)
void sink (void*);
void
test_uint_cst (void)
{
const unsigned max = UINT_MAX;
sink (f_uint_1 (0));
sink (f_uint_1 (1));
sink (f_uint_1 (1233));
sink (f_uint_1 (1234));
sink (f_uint_1 (1235)); /* { dg-warning "argument 1 value .1235u?. exceeds maximum object size 1234" } */
sink (f_uint_1 (max - 1)); /* { dg-warning "argument 1 value .\[0-9\]+u?. exceeds maximum object size 1234" } */
sink (f_uint_1 (max)); /* { dg-warning "argument 1 value .\[0-9\]+u?. exceeds maximum object size 1234" } */
}
void
test_uint_range (unsigned n)
{
const unsigned max = UINT_MAX;
sink (f_uint_1 (n));
sink (f_uint_1 (UR (0, 1)));
sink (f_uint_1 (UR (0, 1233)));
sink (f_uint_1 (UR (0, 1234)));
sink (f_uint_1 (UR (0, 1235)));
sink (f_uint_1 (UR (1, 1235)));
sink (f_uint_1 (UR (1234, 1235)));
sink (f_uint_1 (UR (1235, 1236))); /* { dg-warning "argument 1 range \\\[\[0-9\]+u?, \[0-9\]+u?\\\] exceeds maximum object size 1234" } */
sink (f_uint_1 (UR (1, max - 1)));
sink (f_uint_1 (UR (1, max)));
}
void
test_int_cst (void)
{
const int min = INT_MIN;
const int max = INT_MAX;
sink (f_int_1 (min)); /* { dg-warning "argument 1 value .-\[0-9\]+. is negative" } */
sink (f_int_1 (-1)); /* { dg-warning "argument 1 value .-1. is negative" } */
sink (f_int_1 (0));
sink (f_int_1 (1));
sink (f_int_1 (1233));
sink (f_int_1 (1234));
sink (f_int_1 (max)); /* { dg-warning "argument 1 value .\[0-9\]+u?. exceeds maximum object size 1234" } */
}
void
test_int_range (int n)
{
const int min = INT_MIN;
const int max = INT_MAX;
sink (f_int_1 (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\]+\[lu\]*, \[0-9\]+\[lu\]*\\\] 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 (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" } */
}
void
test_size_cst (void)
{
const size_t max = __SIZE_MAX__;
sink (f_size_1 (0));
sink (f_size_1 (1));
sink (f_size_2 ( 0, 1234));
sink (f_size_2 ( 1, 1234));
sink (f_size_2 ( 2, 1234)); /* { dg-warning "product .2\[lu\]* \\* 1234\[lu\]*. of arguments 1 and 2 exceeds maximum object size \[0-9\]+" } */
sink (f_size_2 (1234, 1234)); /* { dg-warning "product .1234\[lu\]* \\* 1234\[lu\]*. of arguments 1 and 2 exceeds maximum object size 1234" } */
sink (f_size_2 (1235, 1234)); /* { dg-warning "argument 1 value .1235\[lu\]*. exceeds maximum object size 1234" } */
sink (f_size_2 (1234, 1235)); /* { dg-warning "argument 2 value .1235\[lu\]*. exceeds maximum object size 1234" } */
sink (f_size_2 (1234, max)); /* { dg-warning "argument 2 value .\[0-9\]+\[lu\]*. exceeds maximum object size 1234" } */
sink (f_size_2 (max, 1234)); /* { dg-warning "argument 1 value .\[0-9\]+\[lu\]*. exceeds maximum object size 1234" } */
}
void
test_size_range (size_t n)
{
const size_t max = __SIZE_MAX__;
sink (f_size_1 (n));
sink (f_size_1 (UR (0, 1)));
sink (f_size_1 (UR (0, max - 1)));
sink (f_size_1 (UR (1, max - 1)));
sink (f_size_1 (UR (1, max)));
sink (f_size_1 (UAR (1, 1)));
/* Since the only valid argument in the anti-range below is zero
a warning is expected even though -Walloc-zero is not specified. */
sink (f_size_1 (UAR (1, 1234))); /* { dg-warning "argument 1 range \\\[\[0-9\]+\[lu\]*, \[0-9\]+\[lu\]*\\\] exceeds maximum object size " } */
/* The only valid argument in this range is 1. */
sink (f_size_1 (UAR (2, max / 2)));
sink (f_size_2 (n, n));
sink (f_size_2 (n, 1234));
sink (f_size_2 (1234, n));
sink (f_size_2 (UR (0, 1), 1234));
sink (f_size_2 (UR (0, 1), 1235)); /* { dg-warning "argument 2 value .1235\[lu\]*. exceeds maximum object size 1234" } */
sink (f_size_2 (UR (1235, 1236), n)); /* { dg-warning "argument 1 range \\\[1235\[lu\]*, 1236\[lu\]*\\\] exceeds maximum object size 1234" } */
sink (f_size_2 (UR (1235, 1236), UR (max / 2, max))); /* { dg-warning "argument 1 range \\\[\[0-9\]+\[lu\]*, \[0-9\]+\[lu\]*\\\] exceeds maximum object size " } */
/* { dg-warning "argument 2 range \\\[\[0-9\]+\[lu\]*, \[0-9\]+\[lu\]*\\\] exceeds maximum object size " "argument 2" { target *-*-* } .-1 } */
}
/* PR c/78284 - warn on malloc with very large arguments
Test exercising the ability to detect and diagnose calls to allocation
functions decorated with attribute alloc_size that attempt to allocate
zero bytes. For standard allocation functions the return value is
implementation-defined and so relying on it may be a source of bugs. */
/* { dg-do compile } */
/* { dg-options "-O2 -Wall -Walloc-zero" } */
#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 - 1L)
#define ULONG_MAX (LONG_MAX * 2LU + 1)
#define LLONG_MAX __LLONG_MAX__
#define LLONG_MIN (-LLONG_MAX - 1LL)
#define ULLONG_MAX (ULLONG_MAX * 2LLU + 1)
#define SIZE_MAX __SIZE_MAX__
typedef __SIZE_TYPE__ size_t;
#define ALLOC_SIZE(...) __attribute__ ((alloc_size (__VA_ARGS__)))
void* f_uchar_1 (unsigned char) ALLOC_SIZE (1);
void* f_uchar_2 (unsigned char, unsigned char) ALLOC_SIZE (1, 2);
void* f_schar_1 (signed char) ALLOC_SIZE (1);
void* f_schar_2 (signed char, signed char) ALLOC_SIZE (1, 2);
void* f_ushrt_1 (unsigned short) ALLOC_SIZE (1);
void* f_ushrt_2 (unsigned short, unsigned short) ALLOC_SIZE (1, 2);
void* f_shrt_1 (signed short) ALLOC_SIZE (1);
void* f_shrt_2 (signed short, signed short) ALLOC_SIZE (1, 2);
void* f_uint_1 (unsigned) ALLOC_SIZE (1);
void* f_uint_2 (unsigned, unsigned) ALLOC_SIZE (1, 2);
void* f_int_1 (int) ALLOC_SIZE (1);
void* f_int_2 (int, int) ALLOC_SIZE (1, 2);
void* f_ulong_1 (unsigned long) ALLOC_SIZE (1);
void* f_ulong_2 (unsigned long, unsigned long) ALLOC_SIZE (1, 2);
void* f_long_1 (long) ALLOC_SIZE (1);
void* f_long_2 (long, long) ALLOC_SIZE (1, 2);
void* f_ullong_1 (unsigned long long) ALLOC_SIZE (1);
void* f_ullong_2 (unsigned long long, unsigned long long) ALLOC_SIZE (1, 2);
void* f_llong_1 (long long) ALLOC_SIZE (1);
void* f_llong_2 (long long, long long) ALLOC_SIZE (1, 2);
void* f_size_1 (size_t) ALLOC_SIZE (1);
void* f_size_2 (size_t, size_t) ALLOC_SIZE (1, 2);
void* f_size_1_nonnull (size_t)
ALLOC_SIZE (1) __attribute__ ((returns_nonnull));
void* f_size_2_nonnull (size_t, size_t)
ALLOC_SIZE (1, 2) __attribute__ ((returns_nonnull));
void sink (void*);
void
test_uchar (unsigned char n)
{
sink (f_uchar_1 (0)); /* { dg-warning "argument 1 value is zero" } */
sink (f_uchar_2 (0, 1)); /* { dg-warning "argument 1 value is zero" } */
sink (f_uchar_2 (1, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_uchar_2 (n, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_uchar_2 (0, n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_uchar_1 (n));
n = 0;
sink (f_uchar_1 (n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_uchar_2 (1, n)); /* { dg-warning "argument 2 value is zero" } */
}
void
test_schar (signed char n)
{
sink (f_schar_1 (0)); /* { dg-warning "argument 1 value is zero" } */
sink (f_schar_2 (0, 1)); /* { dg-warning "argument 1 value is zero" } */
sink (f_schar_2 (1, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_schar_2 (n, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_schar_2 (0, n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_schar_1 (n));
n = 0;
sink (f_schar_1 (n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_schar_2 (1, n)); /* { dg-warning "argument 2 value is zero" } */
}
void
test_ushrt (unsigned short n)
{
sink (f_ushrt_1 (0)); /* { dg-warning "argument 1 value is zero" } */
sink (f_ushrt_2 (0, 1)); /* { dg-warning "argument 1 value is zero" } */
sink (f_ushrt_2 (1, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_ushrt_2 (n, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_ushrt_2 (0, n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_ushrt_1 (n));
n = 0;
sink (f_ushrt_1 (n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_ushrt_2 (1, n)); /* { dg-warning "argument 2 value is zero" } */
}
void
test_shrt (short n)
{
sink (f_shrt_1 (0)); /* { dg-warning "argument 1 value is zero" } */
sink (f_shrt_2 (0, 1)); /* { dg-warning "argument 1 value is zero" } */
sink (f_shrt_2 (1, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_shrt_2 (n, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_shrt_2 (0, n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_shrt_1 (n));
n = 0;
sink (f_shrt_1 (n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_shrt_2 (1, n)); /* { dg-warning "argument 2 value is zero" } */
}
void
test_uint (unsigned n)
{
sink (f_uint_1 (0)); /* { dg-warning "argument 1 value is zero" } */
sink (f_uint_2 (0, 1)); /* { dg-warning "argument 1 value is zero" } */
sink (f_uint_2 (1, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_uint_2 (n, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_uint_2 (0, n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_uint_1 (n));
n = 0;
sink (f_uint_1 (n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_uint_2 (1, n)); /* { dg-warning "argument 2 value is zero" } */
}
void
test_int (int n)
{
sink (f_int_1 (0)); /* { dg-warning "argument 1 value is zero" } */
sink (f_int_2 (0, 1)); /* { dg-warning "argument 1 value is zero" } */
sink (f_int_2 (1, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_int_2 (n, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_int_2 (0, n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_int_1 (n));
n = 0;
sink (f_int_1 (n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_int_2 (1, n)); /* { dg-warning "argument 2 value is zero" } */
}
void
test_ulong (unsigned long n)
{
sink (f_ulong_1 (0)); /* { dg-warning "argument 1 value is zero" } */
sink (f_ulong_2 (0, 1)); /* { dg-warning "argument 1 value is zero" } */
sink (f_ulong_2 (1, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_ulong_2 (n, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_ulong_2 (0, n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_ulong_1 (n));
n = 0;
sink (f_ulong_1 (n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_ulong_2 (1, n)); /* { dg-warning "argument 2 value is zero" } */
}
void
test_long (long n)
{
sink (f_long_1 (0)); /* { dg-warning "argument 1 value is zero" } */
sink (f_long_2 (0, 1)); /* { dg-warning "argument 1 value is zero" } */
sink (f_long_2 (1, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_long_2 (n, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_long_2 (0, n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_long_1 (n));
n = 0;
sink (f_long_1 (n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_long_2 (1, n)); /* { dg-warning "argument 2 value is zero" } */
}
void
test_size (size_t n)
{
sink (f_size_1 (0)); /* { dg-warning "argument 1 value is zero" } */
sink (f_size_2 (0, 1)); /* { dg-warning "argument 1 value is zero" } */
sink (f_size_2 (1, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_size_2 (n, 0)); /* { dg-warning "argument 2 value is zero" } */
sink (f_size_2 (0, n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_size_1 (n));
n = 0;
sink (f_size_1 (n)); /* { dg-warning "argument 1 value is zero" } */
sink (f_size_2 (1, n)); /* { dg-warning "argument 2 value is zero" } */
}
/* Verify that calls to allocation function decorated with attribute
returns_nonnull don't cause warnings (unlike functions like malloc
that can return null in this case there's nothing to warn about
because a returns_nonnull function guarantees success). */
void
test_size_nonnull (size_t n)
{
sink (f_size_1_nonnull (0));
sink (f_size_2_nonnull (0, 1));
sink (f_size_2_nonnull (1, 0));
sink (f_size_2_nonnull (n, 0));
sink (f_size_2_nonnull (0, n));
sink (f_size_1_nonnull (n));
n = 0;
sink (f_size_1_nonnull (n));
sink (f_size_2_nonnull (1, n));
}
/* Verify that call to plain alloca(0) is not diagnosed. */
void
test_alloca (size_t n)
{
extern void* alloca (size_t);
alloca (0);
}
/* PR c/78284 - warn on malloc with very large arguments
Test exercising the ability of the built-in allocation functions
to detect and diagnose, without optimization, calls that attemnpt
to allocate objects in excess of the number of bytes specified by
-Walloc-larger-than=maximum. */
/* { dg-do compile } */
/* { dg-options "-O0 -Wall -Walloc-size-larger-than=12345" } */
#define MAXOBJSZ 12345
typedef __SIZE_TYPE__ size_t;
void sink (void*);
void test_lit (char *p, char *q)
{
sink (__builtin_aligned_alloc (MAXOBJSZ, 1));
sink (__builtin_aligned_alloc (MAXOBJSZ + 1, 1)); /* { dg-warning "argument 1 value .12346\[lu\]*. exceeds maximum object size 12345" } */
sink (__builtin_alloca (MAXOBJSZ));
sink (__builtin_alloca (MAXOBJSZ + 2)); /* { dg-warning "argument 1 value .12347\[lu\]*. exceeds maximum object size 12345" } */
sink (__builtin_calloc (MAXOBJSZ, 1));
sink (__builtin_calloc (1, MAXOBJSZ));
/* Verify that the signed to unsigned conversion below doesn't cause
a warning. */
sink (__builtin_calloc (p - q, 1));
sink (__builtin_calloc (1, q - p));
sink (__builtin_calloc (p - q, MAXOBJSZ));
sink (__builtin_calloc (MAXOBJSZ, q - p));
sink (__builtin_calloc (MAXOBJSZ / 2, 3)); /* { dg-warning "product .6172\[lu\]* \\* 3\[lu\]*. of arguments 1 and 2 exceeds maximum object size 12345" } */
sink (__builtin_calloc (4, MAXOBJSZ / 3)); /* { dg-warning "product .4\[lu\]* \\* 4115\[lu\]*. of arguments 1 and 2 exceeds maximum object size 12345" } */
sink (__builtin_malloc (MAXOBJSZ));
sink (__builtin_malloc (MAXOBJSZ + 3)); /* { dg-warning "argument 1 value .12348\[lu\]*. exceeds maximum object size 12345" } */
sink (__builtin_realloc (p, MAXOBJSZ));
sink (__builtin_realloc (p, MAXOBJSZ + 4)); /* { dg-warning "argument 2 value .12349\[lu\]*. exceeds maximum object size 12345" } */
}
enum { max = MAXOBJSZ };
void test_cst (char *p, char *q)
{
sink (__builtin_aligned_alloc (max, 1));
sink (__builtin_aligned_alloc (max + 1, 1)); /* { dg-warning "argument 1 value .12346\[lu\]*. exceeds maximum object size 12345" } */
sink (__builtin_alloca (max));
sink (__builtin_alloca (max + 2)); /* { dg-warning "argument 1 value .12347\[lu\]*. exceeds maximum object size 12345" } */
sink (__builtin_calloc (max, 1));
sink (__builtin_calloc (1, max));
/* Verify that the signed to unsigned conversion below doesn't cause
a warning. */
sink (__builtin_calloc (p - q, 1));
sink (__builtin_calloc (1, q - p));
sink (__builtin_calloc (p - q, max));
sink (__builtin_calloc (max, q - p));
sink (__builtin_calloc (max / 2, 3)); /* { dg-warning "product .6172\[lu\]* \\* 3\[lu\]*. of arguments 1 and 2 exceeds maximum object size 12345" } */
sink (__builtin_calloc (4, max / 3)); /* { dg-warning "product .4\[lu\]* \\* 4115\[lu\]*. of arguments 1 and 2 exceeds maximum object size 12345" } */
sink (__builtin_malloc (max));
sink (__builtin_malloc (max + 3)); /* { dg-warning "argument 1 value .12348\[lu\]*. exceeds maximum object size 12345" } */
sink (__builtin_realloc (p, max));
sink (__builtin_realloc (p, max + 4)); /* { dg-warning "argument 2 value .12349\[lu\]*. exceeds maximum object size 12345" } */
}
/* PR c/78284 - warn on malloc with very large arguments
Test exercising the ability of the built-in allocation functions to
detect and diagnose calls that attemnpt to allocate objects in excess
of the maximum specified by -Walloc-size-larger-than=maximum. */
/* { dg-do compile } */
/* { dg-options "-O2 -Wall -Walloc-size-larger-than=12345" } */
#define SIZE_MAX __SIZE_MAX__
#define MAXOBJSZ 12345
typedef __SIZE_TYPE__ size_t;
void sink (void*);
size_t maxobjsize (void)
{
return MAXOBJSZ;
}
void test_var (void *p)
{
size_t max = maxobjsize ();
sink (__builtin_aligned_alloc (max, 1));
sink (__builtin_aligned_alloc (max + 1, 1)); /* { dg-warning "argument 1 value .12346\[lu\]*. exceeds maximum object size 12345" } */
sink (__builtin_alloca (max));
sink (__builtin_alloca (max + 2)); /* { dg-warning "argument 1 value .12347\[lu\]*. exceeds maximum object size 12345" } */
sink (__builtin_calloc (1, max));
sink (__builtin_calloc (max, 1));
sink (__builtin_calloc (max / 2, 3)); /* { dg-warning "product .6172\[lu\]* \\* 3\[lu\]*. of arguments 1 and 2 exceeds maximum object size 12345" } */
sink (__builtin_calloc (4, max / 3)); /* { dg-warning "product .4\[lu\]* \\* 4115\[lu\]*. of arguments 1 and 2 exceeds maximum object size 12345" } */
sink (__builtin_malloc (max));
sink (__builtin_malloc (max + 3)); /* { dg-warning "argument 1 value .12348\[lu\]*. exceeds maximum object size 12345" } */
sink (__builtin_realloc (p, max));
sink (__builtin_realloc (p, max + 4)); /* { dg-warning "argument 2 value .12349\[lu\]*. exceeds maximum object size 12345" } */
}
void test_range (void *p, size_t range)
{
/* Make sure the variable is at least as large as the maximum object
size but also make sure that it's guaranteed not to be too big to
increment (and wrap around). */
size_t max = maxobjsize ();
if (range < max || 2 * max <= range)
range = maxobjsize ();
sink (__builtin_aligned_alloc (range, 1));
sink (__builtin_aligned_alloc (range + 1, 1)); /* { dg-warning "argument 1 range \\\[12346\[lu\]*, \[0-9\]+\[lu\]*\\\] exceeds maximum object size 12345" } */
sink (__builtin_alloca (range));
sink (__builtin_alloca (range + 2)); /* { dg-warning "argument 1 range \\\[12347\[lu\]*, \[0-9\]+\[lu\]*\\\] exceeds maximum object size 12345" } */
sink (__builtin_calloc (range, 1));
sink (__builtin_calloc (1, range));
sink (__builtin_calloc (range / 2, 3)); /* { dg-warning "product .6172\[lu\]* \\* 3\[lu\]*. of arguments 1 and 2 exceeds maximum object size 12345" } */
sink (__builtin_calloc (4, range / 3)); /* { dg-warning "product .4\[lu\]* \\* 4115\[lu\]*. of arguments 1 and 2 exceeds maximum object size 12345" } */
sink (__builtin_malloc (range));
sink (__builtin_malloc (range + 3)); /* { dg-warning "argument 1 range \\\[12348\[lu\]*, 24692\[lu\]*\\\] exceeds maximum object size 12345" } */
sink (__builtin_realloc (p, range));
sink (__builtin_realloc (p, range + 4)); /* { dg-warning "argument 2 range \\\[12349\[lu\]*, 24693\[lu\]*\\\] exceeds maximum object size 12345" } */
}
/* PR c/78284 - warn on malloc with very large arguments
Test to exercise the interaction of the -Walloca-larger-than,
-Wvla-larger-than, and -Walloc-size-larger-than options. The former
two more specific options override the more general latter option. */
/* { dg-do compile } */
/* { dg-options "-O2 -Walloc-size-larger-than=123 -Walloca-larger-than=234 -Wvla-larger-than=345" } */
#define SIZE_MAX __SIZE_MAX__
typedef __SIZE_TYPE__ size_t;
void sink (void*);
size_t alloc_size_limit (void)
{
return 123;
}
size_t alloca_limit (void)
{
return 234;
}
size_t vla_limit (void)
{
return 345;
}
void test_alloca (void)
{
void *p;
/* No warning should be issued for the following call because the more
permissive alloca limit overrides the stricter alloc_size limit. */
p = __builtin_alloca (alloca_limit ());
sink (p);
p = __builtin_alloca (alloca_limit () + 1); /* { dg-warning "argument to .alloca. is too large" } */
sink (p);
}
void test_vla (void)
{
/* Same as above, no warning should be issued here because the more
permissive VLA limit overrides the stricter alloc_size limit. */
char vla1 [vla_limit ()];
sink (vla1);
char vla2 [vla_limit () + 1]; /* { dg-warning "argument to variable-length array is too large" } */
sink (vla2);
}
void test_malloc (void)
{
void *p;
p = __builtin_malloc (alloc_size_limit ());
sink (p);
p = __builtin_malloc (alloc_size_limit () + 1); /* { dg-warning "argument 1 value .124\[lu\]*. exceeds maximum object size 123" } */
sink (p);
}
/* PR c/78284 - warn on malloc with very large arguments
Test verifying that the built-in allocation functions are declared
with attribute malloc. This means that the pointer they return
can be assumed not to alias any other valid pointer. */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
void sink (void*);
extern int x;
#define TEST(call) \
do { \
p = call; \
x = 123; \
*(int*)p = 456; \
(x == 123) ? (void)0 : __builtin_abort (); \
sink (p); \
} while (0)
void test (void *p, unsigned n)
{
TEST (__builtin_aligned_alloc (n, 8));
TEST (__builtin_alloca (n));
TEST (__builtin_calloc (4, n));
TEST (__builtin_malloc (n));
TEST (__builtin_realloc (p, n + 1));
}
/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
......@@ -10,6 +10,7 @@ int main()
{
void * volatile p;
errno = 0;
/* The malloc call below may cause a -Walloc-size-larger-than warning. */
p = malloc (-1);
if (errno != 0)
do_not_optimize_away ();
......@@ -17,3 +18,4 @@ int main()
}
/* { dg-final { scan-assembler "do_not_optimize_away" } } */
/* { dg-prune-output "exceeds maximum object size" } */
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