]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter: Fix handling of variables in anonymous filters
authorOndrej Zajicek <santiago@crfreenet.org>
Tue, 18 Oct 2022 01:58:19 +0000 (03:58 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Tue, 18 Oct 2022 01:58:19 +0000 (03:58 +0200)
Define scope for anonymous filters, and also explicitly distinguish block
scopes and function/filter scopes instead of using anonymous / named
distinction.

Anonymous filters forgot to push scope, so variables for them were in
fact defined in the top scope and therefore they shared a frame. This got
broken after rework of variables, which assumed that there is a named
scope for every function/filter.

conf/cf-lex.l
conf/conf.h
filter/config.Y

index d6f46223c984bc1ca79047e1fa94e10d346f0bb8..28d9ba504e30f67794da5a6bdd7ce9f039e52627 100644 (file)
@@ -812,7 +812,7 @@ cf_push_soft_scope(void)
   if (conf_this_scope->soft_scopes < 0xfe)
     conf_this_scope->soft_scopes++;
   else
-    cf_push_scope(NULL);
+    cf_push_block_scope();
 }
 
 /**
@@ -826,7 +826,7 @@ cf_pop_soft_scope(void)
   if (conf_this_scope->soft_scopes)
     conf_this_scope->soft_scopes--;
   else
-    cf_pop_scope();
+    cf_pop_block_scope();
 }
 
 /**
@@ -841,7 +841,7 @@ cf_swap_soft_scope(void)
   if (conf_this_scope->soft_scopes)
   {
     conf_this_scope->soft_scopes--;
-    cf_push_scope(NULL);
+    cf_push_block_scope();
   }
 }
 
index be46f172d8b378975ea547bcf0b06e58fbe7b460..96c873df8c15e32ad5e5214f83ca82a14a3940b5 100644 (file)
@@ -134,6 +134,7 @@ struct sym_scope {
   struct symbol *name;                 /* Name of this scope */
   uint slots;                          /* Variable slots */
   byte active;                         /* Currently entered */
+  byte block;                          /* No independent stack frame */
   byte soft_scopes;                    /* Number of soft scopes above */
 };
 
@@ -220,6 +221,12 @@ void cf_pop_scope(void);
 void cf_push_soft_scope(void);
 void cf_pop_soft_scope(void);
 
+static inline void cf_push_block_scope(void)
+{ cf_push_scope(NULL); conf_this_scope->block = 1; }
+
+static inline void cf_pop_block_scope(void)
+{ ASSERT(conf_this_scope->block); cf_pop_scope(); }
+
 char *cf_symbol_class_name(struct symbol *sym);
 
 /* Parser */
index f9d9b0b32c5da075f0d2f4e70f98fbc63f445520..68ee1a847c9de0168e8b4f720437e9cf9763f6ea 100644 (file)
@@ -28,9 +28,9 @@ f_new_var(struct sym_scope *s)
   /*
    * - A variable is an offset on vstack from vbase.
    * - Vbase is set on filter start / function call.
-   * - Scopes contain anonymous scopes (blocks) inside filter/function scope
+   * - Scopes contain (non-frame) block scopes inside filter/function scope
    * - Each scope knows number of vars in that scope
-   * - Offset is therefore a sum of 'slots' up to named scope
+   * - Offset is therefore a sum of 'slots' up to filter/function scope
    * - New variables are added on top of vstk, so intermediate values cannot
    *   be there during FI_VAR_INIT. I.e. no 'var' inside 'term'.
    * - Also, each f_line must always have its scope, otherwise a variable may
@@ -39,7 +39,7 @@ f_new_var(struct sym_scope *s)
 
   int offset = s->slots++;
 
-  while (!s->name)
+  while (s->block)
   {
     s = s->next;
     ASSERT(s);
@@ -465,10 +465,12 @@ filter:
      cf_assert_symbol($1, SYM_FILTER);
      $$ = $1->filter;
    }
- | filter_body {
+ | { cf_push_scope(NULL); } filter_body {
      struct filter *f = cfg_alloc(sizeof(struct filter));
-     *f = (struct filter) { .root = $1 };
+     *f = (struct filter) { .root = $2 };
      $$ = f;
+
+     cf_pop_scope();
    }
  ;
 
@@ -913,13 +915,13 @@ cmd:
    }
  | FOR {
      /* Reserve space for walk data on stack */
-     cf_push_scope(NULL);
+     cf_push_block_scope();
      conf_this_scope->slots += 2;
    } for_var IN
    /* Parse term in the parent scope */
    { conf_this_scope->active = 0; } term { conf_this_scope->active = 1; }
    DO cmd {
-     cf_pop_scope();
+     cf_pop_block_scope();
      $$ = f_new_inst(FI_FOR_INIT, $6, $3);
      $$->next = f_new_inst(FI_FOR_NEXT, $3, $9);
    }