From 4d406f14e7cabe23ff4999b41c8ca93311e3ab77 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Mon, 21 Oct 2019 21:55:57 +0200 Subject: [PATCH] Filter: Reintroduce checking of function argument types Seems like during filter rewrite we lost type validation for function arguments. --- filter/config.Y | 38 +++++++++++++++++++++++++++----------- filter/data.h | 4 ++++ filter/f-inst.c | 22 ++++++++++++++++++++-- filter/filter.h | 2 ++ 4 files changed, 53 insertions(+), 13 deletions(-) diff --git a/filter/config.Y b/filter/config.Y index 08c861ce..d89c9884 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -10,6 +10,7 @@ CF_HDR +#include "lib/buffer.h" #include "filter/f-inst.h" #include "filter/data.h" @@ -22,6 +23,8 @@ static inline u32 pair_b(u32 p) { return p & 0xFFFF; } #define f_generate_complex(fi_code, da, arg) \ f_new_inst(FI_EA_SET, f_new_inst(fi_code, f_new_inst(FI_EA_GET, da), arg), da) +BUFFER_(struct f_arg) this_args; + /* * Sets and their items are during parsing handled as lists, linked * through left ptr. The first item in a list also contains a pointer @@ -455,7 +458,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, %type lvalue %type type function_args function_vars %type ec_kind -%type break_command +%type break_command %type cnum %type pair_item ec_item lc_item set_item switch_item set_items switch_items switch_body %type fprefix_set @@ -553,20 +556,27 @@ type: } ; -function_argsn: - /* EMPTY */ - | function_argsn type symbol ';' { - if ($3->scope->slots >= 0xfe) cf_error("Too many declarations, at most 255 allowed"); - cf_define_symbol($3, SYM_VARIABLE | $2, offset, $3->scope->slots++); +function_arg: + type symbol { + cf_define_symbol($2, SYM_VARIABLE | $1, offset, $2->scope->slots++); + BUFFER_PUSH(this_args) = (struct f_arg){ .type = $1 }; } ; +function_argsn: + /* EMPTY */ { + /* Initialize the buffer */ + if (!this_args.data) + BUFFER_INIT(this_args, &root_pool, 4); + else + BUFFER_FLUSH(this_args); + } + | function_argsn function_arg ';' + ; + function_args: '(' ')' { $$ = 0; } - | '(' function_argsn type symbol ')' { - cf_define_symbol($4, SYM_VARIABLE | $3, offset, $4->scope->slots++); - $$ = $4->scope->slots; - } + | '(' function_argsn function_arg ')' { $$ = this_args.used; } ; function_vars: @@ -615,7 +625,13 @@ function_def: struct function *fn = cfg_alloc(sizeof(struct function)); *fn = (struct function) { .sym = $2, .body = $5 }; $2->function = fn; - $5->args = $4; + if ($4) { + struct f_arg *args = cfg_alloc(BUFFER_SIZE(this_args)); + memcpy(args, this_args.data, BUFFER_SIZE(this_args)); + fn->args = args; + fn->arg_count = this_args.used; + } + $5->args = fn->arg_count; cf_pop_scope(); } ; diff --git a/filter/data.h b/filter/data.h index 083595f4..b0db4f11 100644 --- a/filter/data.h +++ b/filter/data.h @@ -80,6 +80,10 @@ struct f_val { } val; }; +struct f_arg { + enum f_type type; +}; + /* Dynamic attribute definition (eattrs) */ struct f_dynamic_attr { u8 type; /* EA type (EAF_*) */ diff --git a/filter/f-inst.c b/filter/f-inst.c index c21d48df..4fec9fc3 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -899,9 +899,11 @@ SYMBOL; FID_NEW_BODY() - if (whati->varcount != sym->function->body->args) + const struct function *fn = sym->function; + + if (whati->varcount != fn->arg_count) cf_error("Function call '%s' got %u arguments, needs %u arguments", - sym->name, whati->varcount, sym->function->body->args); + sym->name, whati->varcount, fn->arg_count); /* Add void slot for return value (requires [[NEVER_CONSTANT]]) */ struct f_inst *rv = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_VOID }); @@ -914,6 +916,22 @@ return 0; FID_INTERPRET_BODY() + const struct function *fn = sym->function; + + /* Check types of arguments */ + for (uint i = 0; i < fn->arg_count; i++) + if ((vv(i).type != fn->args[i].type) && (vv(i).type != T_VOID)) + { + /* IP->Quad implicit conversion */ + if ((fn->args[i].type == T_QUAD) && val_is_ip4(&vv(i))) + vv(i) = (struct f_val) { + .type = T_QUAD, + .val.i = ipa_to_u32(vv(i).val.ip), + }; + else + runtime("Function call '%s' argument %u must be of type 0x%02x, got 0x%02x", + sym->name, i, fn->args[i].type, vv(i).type); + } /* Push the body on stack */ LINEX(sym->function->body); diff --git a/filter/filter.h b/filter/filter.h index 8b790e37..5f82de56 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -53,7 +53,9 @@ struct filter { struct function { struct symbol *sym; + const struct f_arg *args; const struct f_line *body; + uint arg_count; }; struct rte;