diff options
author | Richard Biener <rguenther@suse.de> | 2020-02-05 14:04:29 +0100 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2020-02-05 14:06:40 +0100 |
commit | 1105cf8163f635ac4e4a3357d8b16a73fb6aced5 (patch) | |
tree | beb7961773473aa15a76c9261cda280e556e7e02 /gcc/genmatch.c | |
parent | 5f44a4341cf9793ccfb28cb0ab6876174c0d89dc (diff) | |
download | gcc-1105cf8163f635ac4e4a3357d8b16a73fb6aced5.zip gcc-1105cf8163f635ac4e4a3357d8b16a73fb6aced5.tar.gz gcc-1105cf8163f635ac4e4a3357d8b16a73fb6aced5.tar.bz2 |
middle-end/90648 fend off builtin calls with not enough arguments from match
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.
Diffstat (limited to 'gcc/genmatch.c')
-rw-r--r-- | gcc/genmatch.c | 22 |
1 files changed, 14 insertions, 8 deletions
diff --git a/gcc/genmatch.c b/gcc/genmatch.c index d174d41..0a8cba6 100644 --- a/gcc/genmatch.c +++ b/gcc/genmatch.c @@ -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"); |