PR 89934 reports yet another ICE due to a call to a library
built-in function with invalid arguments.  The attached patch
does the bare minimum to avoid it.  I will commit it to trunk
and to GCC 8 later this week if there are no objections.

Martin

PS There have been many of these reports (at least three in
the wrestrict pass alone, and quite a few elsewhere).  Simply
avoiding the ICEs as this patch does and as all the others
before it have done as well does nothing to help solve
the underlying problem in user code: the invalid calls will
end up with undefined behavior if they are ever made at runtime.
For example, the one in this bug report will most likely cause
data corruption or buffer overflow without ever being detected
by _FORTIFY_SOURCE.  That seems far worse than failing to compile
the code (either with an ICE or with some
other hard error).

For GCC 10 I think a more robust solution should be put in place
not just to prevent these invalid built-in calls from tripping
up the middle-end, but also to avoid the undefined behavior at
runtime.  The calls could either be rejected with an error as
Clang does, or they could be replaced them with __builtin_trap
or perhaps __builtin_unreachable, depending on some command
line option.

PR middle-end/89934 - ICE on a call with fewer arguments to strncpy declared without prototype

gcc/ChangeLog:

	PR middle-end/89934
	* gimple-ssa-warn-restrict.c (builtin_access::builtin_access): Bail
	out if the number of arguments is less than expected.

gcc/testsuite/ChangeLog:

	PR middle-end/89934
	* gcc.dg/Wrestrict-19.c: New test.
	* gcc.dg/Wrestrict-5.c: Add comment.  Remove unused code.

Index: gcc/gimple-ssa-warn-restrict.c
===================================================================
--- gcc/gimple-ssa-warn-restrict.c	(revision 270061)
+++ gcc/gimple-ssa-warn-restrict.c	(working copy)
@@ -730,6 +730,10 @@ builtin_access::builtin_access (gimple *call, buil
   offset_int bounds[2] = { maxobjsize, maxobjsize };
   if (dstref->strbounded_p)
     {
+      unsigned nargs = gimple_call_num_args (call);
+      if (nargs <= sizeargno)
+	return;
+
       tree size = gimple_call_arg (call, sizeargno);
       tree range[2];
       if (get_size_range (size, range, true))
Index: gcc/testsuite/gcc.dg/Wrestrict-19.c
===================================================================
--- gcc/testsuite/gcc.dg/Wrestrict-19.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/Wrestrict-19.c	(working copy)
@@ -0,0 +1,33 @@
+/* PR middle-end/89934 - ICE on a call with fewer arguments to strncpy
+   declared without prototype
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+char *strncpy ();
+
+char* f0 (char *s)
+{
+  return strncpy ();
+}
+
+char* f1 (char *s)
+{
+  return strncpy (s);
+}
+
+char* f2 (char *s)
+{
+  return strncpy (s, s + 1);   /* ICE here.  */
+}
+
+void f3 (char *s, size_t n, const char *t)
+{
+  strncpy (s, n, t);
+  strncpy (n, s, t);
+}
+
+/* { dg-prune-output "\\\[-Wbuiltin-declaration-mismatch]" }
+   { dg-prune-output "\\\[-Wint-conversion]" } */
+
Index: gcc/testsuite/gcc.dg/Wrestrict-5.c
===================================================================
--- gcc/testsuite/gcc.dg/Wrestrict-5.c	(revision 270061)
+++ gcc/testsuite/gcc.dg/Wrestrict-5.c	(working copy)
@@ -1,20 +1,11 @@
-/* Test to verify that valid calls to common restrict-qualified built-in
+/* PR tree-optimization/83655 - ICE on an invalid call to memcpy declared
+   with no prototype
+   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-prune-output "conflicting types for built-in" }
   { 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 ();
 

Reply via email to