mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-08 12:18:42 +00:00
Filter: Reintroduce checking of function argument types
Seems like during filter rewrite we lost type validation for function arguments.
This commit is contained in:
parent
3d7939561b
commit
4d406f14e7
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
CF_HDR
|
CF_HDR
|
||||||
|
|
||||||
|
#include "lib/buffer.h"
|
||||||
#include "filter/f-inst.h"
|
#include "filter/f-inst.h"
|
||||||
#include "filter/data.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) \
|
#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)
|
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
|
* Sets and their items are during parsing handled as lists, linked
|
||||||
* through left ptr. The first item in a list also contains a pointer
|
* through left ptr. The first item in a list also contains a pointer
|
||||||
@ -553,20 +556,27 @@ type:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
function_argsn:
|
function_arg:
|
||||||
/* EMPTY */
|
type symbol {
|
||||||
| function_argsn type symbol ';' {
|
cf_define_symbol($2, SYM_VARIABLE | $1, offset, $2->scope->slots++);
|
||||||
if ($3->scope->slots >= 0xfe) cf_error("Too many declarations, at most 255 allowed");
|
BUFFER_PUSH(this_args) = (struct f_arg){ .type = $1 };
|
||||||
cf_define_symbol($3, SYM_VARIABLE | $2, offset, $3->scope->slots++);
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
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:
|
function_args:
|
||||||
'(' ')' { $$ = 0; }
|
'(' ')' { $$ = 0; }
|
||||||
| '(' function_argsn type symbol ')' {
|
| '(' function_argsn function_arg ')' { $$ = this_args.used; }
|
||||||
cf_define_symbol($4, SYM_VARIABLE | $3, offset, $4->scope->slots++);
|
|
||||||
$$ = $4->scope->slots;
|
|
||||||
}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
function_vars:
|
function_vars:
|
||||||
@ -615,7 +625,13 @@ function_def:
|
|||||||
struct function *fn = cfg_alloc(sizeof(struct function));
|
struct function *fn = cfg_alloc(sizeof(struct function));
|
||||||
*fn = (struct function) { .sym = $2, .body = $5 };
|
*fn = (struct function) { .sym = $2, .body = $5 };
|
||||||
$2->function = fn;
|
$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();
|
cf_pop_scope();
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@ -80,6 +80,10 @@ struct f_val {
|
|||||||
} val;
|
} val;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct f_arg {
|
||||||
|
enum f_type type;
|
||||||
|
};
|
||||||
|
|
||||||
/* Dynamic attribute definition (eattrs) */
|
/* Dynamic attribute definition (eattrs) */
|
||||||
struct f_dynamic_attr {
|
struct f_dynamic_attr {
|
||||||
u8 type; /* EA type (EAF_*) */
|
u8 type; /* EA type (EAF_*) */
|
||||||
|
@ -899,9 +899,11 @@
|
|||||||
SYMBOL;
|
SYMBOL;
|
||||||
|
|
||||||
FID_NEW_BODY()
|
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",
|
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]]) */
|
/* Add void slot for return value (requires [[NEVER_CONSTANT]]) */
|
||||||
struct f_inst *rv = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_VOID });
|
struct f_inst *rv = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_VOID });
|
||||||
@ -914,6 +916,22 @@
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
FID_INTERPRET_BODY()
|
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 */
|
/* Push the body on stack */
|
||||||
LINEX(sym->function->body);
|
LINEX(sym->function->body);
|
||||||
|
@ -53,7 +53,9 @@ struct filter {
|
|||||||
|
|
||||||
struct function {
|
struct function {
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
|
const struct f_arg *args;
|
||||||
const struct f_line *body;
|
const struct f_line *body;
|
||||||
|
uint arg_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rte;
|
struct rte;
|
||||||
|
Loading…
Reference in New Issue
Block a user