middle-end/90648 fend off builtin calls with not enough arguments from match
authorRichard Biener <rguenther@suse.de>
Wed, 5 Feb 2020 13:04:29 +0000 (14:04 +0100)
committerRichard Biener <rguenther@suse.de>
Wed, 5 Feb 2020 13:06:40 +0000 (14:06 +0100)
This adds guards to genmatch generated code before accessing call
expression or stmt arguments that might be out of bounds when
the user provided bogus prototypes for what we consider builtins.

2020-02-05  Richard Biener  <rguenther@suse.de>

PR middle-end/90648
* genmatch.c (dt_node::gen_kids_1): Emit number of argument
checks before matching calls.

* gcc.dg/pr90648.c: New testcase.

gcc/ChangeLog
gcc/genmatch.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr90648.c [new file with mode: 0644]

index a4005841f60aa63e54e5b80f9abccaf2ba36f1c5..072c89171ae69480025a02d9d6fb9d990e145710 100644 (file)
@@ -1,3 +1,9 @@
+2020-02-05  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/90648
+       * genmatch.c (dt_node::gen_kids_1): Emit number of argument
+       checks before matching calls.
+
 2020-02-05  Jakub Jelinek  <jakub@redhat.com>
 
        * tree-ssa-alias.c (aliasing_matching_component_refs_p): Fix up
index d174d4144fd56c0f2de7528c9d0449baa0ec83ec..0a8cba62e0cc1d5e928df39ba961c1a33bf9185e 100644 (file)
@@ -3060,10 +3060,15 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, int depth,
            {
              expr *e = as_a <expr *>(fns[i]->op);
              fprintf_indent (f, indent, "case %s:\n", e->operation->id);
-             fprintf_indent (f, indent, "  {\n");
-             fns[i]->gen (f, indent + 4, true, depth);
-             fprintf_indent (f, indent, "    break;\n");
-             fprintf_indent (f, indent, "  }\n");
+             /* We need to be defensive against bogus prototypes allowing
+                calls with not enough arguments.  */
+             fprintf_indent (f, indent,
+                             "  if (gimple_call_num_args (_c%d) == %d)\n"
+                             "    {\n", depth, e->ops.length ());
+             fns[i]->gen (f, indent + 6, true, depth);
+             fprintf_indent (f, indent,
+                             "    }\n"
+                             "  break;\n");
            }
 
          fprintf_indent (f, indent, "default:;\n");
@@ -3125,10 +3130,11 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, int depth,
          gcc_assert (e->operation->kind == id_base::FN);
 
          fprintf_indent (f, indent, "case %s:\n", e->operation->id);
-         fprintf_indent (f, indent, "  {\n");
-         generic_fns[j]->gen (f, indent + 4, false, depth);
-         fprintf_indent (f, indent, "    break;\n");
-         fprintf_indent (f, indent, "  }\n");
+         fprintf_indent (f, indent, "  if (call_expr_nargs (%s) == %d)\n"
+                                    "    {\n", kid_opname, e->ops.length ());
+         generic_fns[j]->gen (f, indent + 6, false, depth);
+         fprintf_indent (f, indent, "    }\n"
+                                    "  break;\n");
        }
       fprintf_indent (f, indent, "default:;\n");
 
index 584b111cfd23cbc67318e26fffef21333363467b..873a7c415ae70af8e16204e4685fcaa374d55d81 100644 (file)
@@ -1,3 +1,9 @@
+2020-02-05  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/90648
+       * genmatch.c (dt_node::gen_kids_1): Emit number of argument
+       checks before matching calls.
+
 2020-02-05  Jakub Jelinek  <jakub@redhat.com>
 
        PR middle-end/93555
diff --git a/gcc/testsuite/gcc.dg/pr90648.c b/gcc/testsuite/gcc.dg/pr90648.c
new file mode 100644 (file)
index 0000000..bf1fa98
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+extern double copysign ();
+double foo (double x)
+{
+  return x * copysign (); /* { dg-warning "too few arguments" } */
+}