mirror of
				https://gitlab.labs.nic.cz/labs/bird.git
				synced 2024-05-11 16:54:54 +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:
		@@ -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 <flv> lvalue
 | 
			
		||||
%type <i> type function_args function_vars
 | 
			
		||||
%type <ecs> ec_kind
 | 
			
		||||
%type <fret> break_command 
 | 
			
		||||
%type <fret> break_command
 | 
			
		||||
%type <i32> cnum
 | 
			
		||||
%type <e> pair_item ec_item lc_item set_item switch_item set_items switch_items switch_body
 | 
			
		||||
%type <trie> 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();
 | 
			
		||||
   }
 | 
			
		||||
 ;
 | 
			
		||||
 
 | 
			
		||||
@@ -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_*) */
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user