From cf3fc0e8ac5a9b65bb213f979a4030e43243a5fc Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Wed, 3 Jan 2018 23:41:32 +0000 Subject: [PATCH] PR tree-optimization/83655 - ICE on an invalid call to memcpy declared with no prototype gcc/testsuite/ChangeLog: PR tree-optimization/83655 * gcc.dg/Wrestrict-5.c: New test. * c-c++-common/builtins.c: New test. gcc/ChangeLog: PR tree-optimization/83655 * gimple-ssa-warn-restrict.c (wrestrict_dom_walker::check_call): Avoid checking calls with invalid arguments. From-SVN: r256218 --- gcc/ChangeLog | 6 + gcc/gimple-ssa-warn-restrict.c | 13 +- gcc/testsuite/ChangeLog | 6 + gcc/testsuite/c-c++-common/builtins.c | 193 ++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/Wrestrict-5.c | 43 ++++++ 5 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/c-c++-common/builtins.c create mode 100644 gcc/testsuite/gcc.dg/Wrestrict-5.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 78c30df5364..a11d6e361e8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2018-01-03 Martin Sebor + + PR tree-optimization/83655 + * gimple-ssa-warn-restrict.c (wrestrict_dom_walker::check_call): Avoid + checking calls with invalid arguments. + 2018-01-03 Richard Sandiford * tree-vect-stmts.c (vect_get_store_rhs): New function. diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c index 97d2af75531..066be1a0438 100644 --- a/gcc/gimple-ssa-warn-restrict.c +++ b/gcc/gimple-ssa-warn-restrict.c @@ -1693,7 +1693,18 @@ wrestrict_dom_walker::check_call (gcall *call) /* DST and SRC can be null for a call with an insufficient number of arguments to a built-in function declared without a protype. */ - if (!dst || !src || check_bounds_or_overlap (call, dst, src, dstwr, NULL_TREE)) + if (!dst || !src) + return; + + /* DST, SRC, or DSTWR can also have the wrong type in a call to + a function declared without a prototype. Avoid checking such + invalid calls. */ + if (TREE_CODE (TREE_TYPE (dst)) != POINTER_TYPE + || TREE_CODE (TREE_TYPE (src)) != POINTER_TYPE + || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr)))) + return; + + if (check_bounds_or_overlap (call, dst, src, dstwr, NULL_TREE)) return; /* Avoid diagnosing the call again. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a5779f74982..53900981ded 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2018-01-03 Martin Sebor + + PR tree-optimization/83655 + * gcc.dg/Wrestrict-5.c: New test. + * c-c++-common/builtins.c: New test. + 2018-01-03 Richard Sandiford Alan Hayward David Sherwood diff --git a/gcc/testsuite/c-c++-common/builtins.c b/gcc/testsuite/c-c++-common/builtins.c new file mode 100644 index 00000000000..673fcad22aa --- /dev/null +++ b/gcc/testsuite/c-c++-common/builtins.c @@ -0,0 +1,193 @@ +/* Test to verify that calls to common built-in functions declared + with no prototype do not cause an ICE. + { dg-do compile } + { dg-options "-O2 -Wall -Wextra" } + { dg-prune-output "warning" } */ + +typedef __SIZE_TYPE__ size_t; + +#if __cplusplus +extern "C" { + +#define NO_PROTO ... +#else +#define NO_PROTO /* empty */ +#endif + + /* Character classification built-ins from . */ + int isalpha (NO_PROTO); + int isalnum (NO_PROTO); + int isalpha (NO_PROTO); + int iscntrl (NO_PROTO); + int isdigit (NO_PROTO); + int isgraph (NO_PROTO); + int islower (NO_PROTO); + int isprint (NO_PROTO); + int ispunct (NO_PROTO); + int isspace (NO_PROTO); + int isupper (NO_PROTO); + int isxdigit (NO_PROTO); + int tolower (NO_PROTO); + int toupper (NO_PROTO); + + /* Memory allocation built-ins from . */ + void* alloca (NO_PROTO); + void* aligned_alloc (NO_PROTO); + void* calloc (NO_PROTO); + void* malloc (NO_PROTO); + void* realloc (NO_PROTO); + + /* Raw memory built-ins from . */ + void* memcpy (NO_PROTO); + void* memchr (NO_PROTO); + void* memmove (NO_PROTO); + void* mempcpy (NO_PROTO); + void* memset (NO_PROTO); + + /* String built-ins from . */ + char* stpcpy (NO_PROTO); + char* stpncpy (NO_PROTO); + + char* strcat (NO_PROTO); + char* strcpy (NO_PROTO); + + char* strdup (NO_PROTO); + char* strndup (NO_PROTO); + + char* strncat (NO_PROTO); + char* strncpy (NO_PROTO); + + size_t strlen (NO_PROTO); + size_t strnlen (NO_PROTO); + + char* strchr (NO_PROTO); + int strcmp (NO_PROTO); + int strncmp (NO_PROTO); + + /* Input/output functions from . */ + int puts (NO_PROTO); + int fputs (NO_PROTO); + + int scanf (NO_PROTO); + int fscanf (NO_PROTO); + int sscanf (NO_PROTO); + int vfscanf (NO_PROTO); + int vsscanf (NO_PROTO); + + int printf (NO_PROTO); + int fprintf (NO_PROTO); + int sprintf (NO_PROTO); + + int snprintf (NO_PROTO); + + int vprintf (NO_PROTO); + int vfprintf (NO_PROTO); + int vsprintf (NO_PROTO); + + int vsnprintf (NO_PROTO); + +#if __cplusplus +} +#endif + + +#define CONCAT(a, b) a ## b +#define UNIQ_NAME(func, id) CONCAT (test_ ## func ## _, id) + +#define TEST_FUNC(func, arglist) \ + __typeof__ (func arglist) \ + UNIQ_NAME (func, __COUNTER__) (void) { \ + return func arglist; \ + } + +#define T1(func) \ + TEST_FUNC (func, ()); \ + TEST_FUNC (func, (1)); \ + TEST_FUNC (func, ("")); \ + TEST_FUNC (func, ((void*)1)); \ + TEST_FUNC (func, (iarr)); \ + TEST_FUNC (func, (function)) + +#define T2(func) \ + TEST_FUNC (func, (1, 1)); \ + TEST_FUNC (func, (1, "")); \ + TEST_FUNC (func, (1, (void*)1)); \ + TEST_FUNC (func, (1, iarr)); \ + TEST_FUNC (func, (1, function)) + +#define T3(func) \ + TEST_FUNC (func, (1, 1, 1)); \ + TEST_FUNC (func, (1, 1, "")); \ + TEST_FUNC (func, (1, 1, (void*)1)); \ + TEST_FUNC (func, (1, 1, iarr)); \ + TEST_FUNC (func, (1, 1, function)) + +extern int iarr[]; +extern void function (void); + +T1 (isalpha); +T1 (isalnum); +T1 (isalpha); +T1 (iscntrl); +T1 (isdigit); +T1 (isgraph); +T1 (islower); +T1 (isprint); +T1 (ispunct); +T1 (isspace); +T1 (isupper); +T1 (isxdigit); +T1 (tolower); +T1 (toupper); + +T1 (alloca); +T2 (aligned_alloc); +T2 (malloc); +T2 (calloc); +T2 (realloc); + +T3 (memcpy); +T3 (memmove); +T3 (mempcpy); +T3 (memset); +T3 (memchr); + +T2 (stpcpy); +T3 (stpncpy); + +T2 (strcat); +T2 (strcpy); + +T1 (strdup); +T2 (strndup); + +T3 (strncat); +T3 (strncpy); + +T2 (strchr); +T2 (strcmp); +T3 (strncmp); + +T1 (strlen); +T2 (strnlen); + +T1 (puts); +T2 (fputs); + +T1 (scanf); +T2 (fscanf); +T2 (sscanf); +T2 (vfscanf); +T2 (vsscanf); + +T2 (printf); +T3 (fprintf); +T3 (sprintf); + +T3 (snprintf); + +T2 (vprintf); +T2 (vfprintf); +T2 (vsprintf); + +T3 (vsnprintf); diff --git a/gcc/testsuite/gcc.dg/Wrestrict-5.c b/gcc/testsuite/gcc.dg/Wrestrict-5.c new file mode 100644 index 00000000000..4912ee5506b --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wrestrict-5.c @@ -0,0 +1,43 @@ +/* Test to verify that valid calls to common restrict-qualified built-in + functions declared with no prototype are checked for overlap, and that + invalid calls are ignored. + { dg-do compile } + { dg-options "-O2 -Wrestrict" } */ + +typedef __SIZE_TYPE__ size_t; + +#if __cplusplus +extern "C" { + +#define NO_PROTO ... +#else +#define NO_PROTO /* empty */ +#endif + +void* memcpy (); +char* strncpy (); + +#if __cplusplus +} /* extern "C" */ +#endif + +void test_memcpy_warn (char *d) +{ + memcpy (d, d + 2, 3); /* { dg-warning "accessing 3 bytes at offsets 0 and 2 overlaps 1 byte at offset 2" } */ +} + +void test_memcpy_nowarn (char *d) +{ + memcpy (d, d + 2, ""); +} + + +void test_strncpy_warn (char *d) +{ + strncpy (d + 1, d + 3, 5); /* { dg-warning "accessing 5 bytes at offsets 1 and 3 overlaps 2 bytes at offset 3" } */ +} + +void test_strncpy_nowarn (char *d) +{ + strncpy (d + 1, d + 3, ""); +} -- 2.30.2