From 36537a1c41adabc6da23ae19e7c3a933582b19dd Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 22 May 2018 19:37:48 +0000 Subject: [PATCH] PR middle-end/85359 - duplicate -Wstringop-overflow for a strcmp call with a nonstring pointer gcc/ChangeLog: PR middle-end/85359 * builtins.c (expand_builtin_strcpy): Call maybe_warn_nonstring_arg only when expasion succeeds. (expand_builtin_strcmp): Same. (expand_builtin_strncmp): Same. gcc/testsuite/ChangeLog: PR middle-end/85359 * gcc.dg/attr-nonstring.c: New test. From-SVN: r260550 --- gcc/ChangeLog | 8 ++ gcc/builtins.c | 32 ++++--- gcc/calls.c | 5 +- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.dg/attr-nonstring.c | 123 ++++++++++++++++++++++++++ 5 files changed, 161 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/attr-nonstring.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e665b03e1e1..79a5e374d5a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -24,6 +24,14 @@ * config/aarch64/aarch64.md (*ashift_extv_bfiz): New pattern. +2018-05-22 Martin Sebor + + PR middle-end/85359 + * builtins.c (expand_builtin_strcpy): Call maybe_warn_nonstring_arg + only when expasion succeeds. + (expand_builtin_strcmp): Same. + (expand_builtin_strncmp): Same. + 2018-05-22 Martin Sebor * calls.c (maybe_warn_nonstring_arg): Fix a typo in a comment. diff --git a/gcc/builtins.c b/gcc/builtins.c index 9a2bf8c7d38..841c1ef4da7 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -3783,7 +3783,17 @@ expand_builtin_strcpy (tree exp, rtx target) src, destsize); } - return expand_builtin_strcpy_args (dest, src, target); + if (rtx ret = expand_builtin_strcpy_args (dest, src, target)) + { + /* Check to see if the argument was declared attribute nonstring + and if so, issue a warning since at this point it's not known + to be nul-terminated. */ + tree fndecl = get_callee_fndecl (exp); + maybe_warn_nonstring_arg (fndecl, exp); + return ret; + } + + return NULL_RTX; } /* Helper function to do the actual work for expand_builtin_strcpy. The @@ -4576,14 +4586,14 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target) } } - /* Check to see if the argument was declared attribute nonstring - and if so, issue a warning since at this point it's not known - to be nul-terminated. */ tree fndecl = get_callee_fndecl (exp); - maybe_warn_nonstring_arg (fndecl, exp); - if (result) { + /* Check to see if the argument was declared attribute nonstring + and if so, issue a warning since at this point it's not known + to be nul-terminated. */ + maybe_warn_nonstring_arg (fndecl, exp); + /* Return the value in the proper mode for this function. */ machine_mode mode = TYPE_MODE (TREE_TYPE (exp)); if (GET_MODE (result) == mode) @@ -4680,14 +4690,14 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target, arg2_rtx, TREE_TYPE (len), arg3_rtx, MIN (arg1_align, arg2_align)); - /* Check to see if the argument was declared attribute nonstring - and if so, issue a warning since at this point it's not known - to be nul-terminated. */ tree fndecl = get_callee_fndecl (exp); - maybe_warn_nonstring_arg (fndecl, exp); - if (result) { + /* Check to see if the argument was declared attribute nonstring + and if so, issue a warning since at this point it's not known + to be nul-terminated. */ + maybe_warn_nonstring_arg (fndecl, exp); + /* Return the value in the proper mode for this function. */ mode = TYPE_MODE (TREE_TYPE (exp)); if (GET_MODE (result) == mode) diff --git a/gcc/calls.c b/gcc/calls.c index 9d8b96f34ad..35bcff7c6e5 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1671,7 +1671,10 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp) /* Determine the range of the bound argument (if specified). */ tree bndrng[2] = { NULL_TREE, NULL_TREE }; if (bound) - get_size_range (bound, bndrng); + { + STRIP_NOPS (bound); + get_size_range (bound, bndrng); + } if (*lenrng) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2e5bb3f0fb1..bd1007f761e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-05-22 Martin Sebor + + PR middle-end/85359 + * gcc.dg/attr-nonstring.c: New test. + 2018-05-22 H.J. Lu PR target/85345 diff --git a/gcc/testsuite/gcc.dg/attr-nonstring.c b/gcc/testsuite/gcc.dg/attr-nonstring.c new file mode 100644 index 00000000000..46f5c0d7c59 --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-nonstring.c @@ -0,0 +1,123 @@ +/* PR middle-end/85359 - duplicate -Wstringop-overflow for a strcmp call + with a nonstring pointer + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +typedef __SIZE_TYPE__ size_t; +typedef __builtin_va_list va_list; + +int printf (const char*, ...); +int puts (const char*); +int puts_unlocked (const char*); +int sprintf (char*, const char*, ...); +int snprintf (char*, size_t, const char*, ...); +int vsprintf (char*, const char*, va_list); +int vsnprintf (char*, size_t, const char*, va_list); + +int strcmp (const char*, const char*); +int strncmp (const char*, const char*, size_t); + +char* stpcpy (char*, const char*); +char* stpncpy (char*, const char*, size_t); + +char* strcat (char*, const char*); +char* strncat (char*, const char*, size_t); + +char* strcpy (char*, const char*); +char* strncpy (char*, const char*, size_t); + +char* strchr (const char*, int); +char* strrchr (const char*, int); +char* strstr (const char*, const char*); +char* strdup (const char*); +size_t strlen (const char*); +size_t strnlen (const char*, size_t); +char* strndup (const char*, size_t); + +#define NONSTRING __attribute__ ((nonstring)) + +extern char ns5[5] NONSTRING; + +int strcmp_nonstring_1 (NONSTRING const char *a, const char *b) +{ + /* dg-warning matches one or more instances of the warning so it's + 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" } */ +} + +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" } */ +} + +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" } */ +} + +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" } */ +} + +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" } */ +} + +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" } */ +} + +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" } */ +} + +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" } */ +} + +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" } */ +} + +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" } */ +} + +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" } */ +} + +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" } */ +} + +char* stdup_nonstring (NONSTRING const char *s) +{ + return strdup (s); /* { dg-regexp "\[^\n\r\]+: warning: .strdup. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "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" } */ +} + +int printf_nonstring (NONSTRING const char *s) +{ + return printf (s); /* { dg-regexp "\[^\n\r\]+: warning: .printf. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "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" } */ +} -- 2.30.2