Commit 4d406f14 authored by Ondrej Zajicek (work)'s avatar Ondrej Zajicek (work)
Browse files

Filter: Reintroduce checking of function argument types

Seems like during filter rewrite we lost type validation for function
arguments.
parent 3d793956
Loading
Loading
Loading
Loading
+26 −10
Original line number Diff line number Diff line
@@ -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
@@ -553,20 +556,27 @@ type:
   }
 ;

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 */
 | 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++);
   /* 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();
   }
 ;
+4 −0
Original line number Diff line number Diff line
@@ -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_*) */
+20 −2
Original line number Diff line number Diff line
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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;