]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Clear local variables in filters and functions.
authorOndrej Zajicek <santiago@crfreenet.org>
Fri, 19 Mar 2010 08:41:18 +0000 (09:41 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Fri, 19 Mar 2010 08:41:18 +0000 (09:41 +0100)
Fixes crash when used uninitialized variables.
This problem was surprisingly tricky to fix.

filter/config.Y
filter/filter.c
filter/test.conf

index fcbee7140d6788b9e61d2d386b862cf8e028c988..1af5649c96661420900b4d8bc445ba97018024f1 100644 (file)
@@ -172,7 +172,14 @@ function_params:
 
 function_body:
    decls '{' cmds '}' {
-     $$ = $3;
+     if ($1) {
+       /* Prepend instruction to clear local variables */
+       $$ = f_new_inst();
+       $$->code = P('c','v');
+       $$->a1.p = $1;
+       $$->next = $3;
+     } else
+       $$ = $3;
    }
  ;
 
index bfb480ab7862dc47c5f20aafb25713dc46a9bfe0..de7a97bc625c9e732663071638bb08ac6c2b3365 100644 (file)
@@ -473,27 +473,10 @@ interpret(struct f_inst *what)
   case 's':
     ARG(v2, a2.p);
     sym = what->a1.p;
-    switch (res.type = v2.type) {
-    case T_VOID: runtime( "Can't assign void values" );
-    case T_ENUM:
-    case T_BOOL:
-    case T_INT:
-    case T_PAIR:
-    case T_STRING:
-    case T_IP:
-    case T_PREFIX:
-    case T_PREFIX_SET:
-    case T_SET:
-    case T_PATH:
-    case T_PATH_MASK:
-    case T_CLIST:
-      if (sym->class != (SYM_VARIABLE | v2.type))
-       runtime( "Assigning to variable of incompatible type" );
-      * (struct f_val *) sym->def = v2; 
-      break;
-    default:
-      bug( "Set to invalid type" );
-    }
+    if ((sym->class != (SYM_VARIABLE | v2.type)) &&
+       (v2.type != T_VOID))
+      runtime( "Assigning to variable of incompatible type" );
+    * (struct f_val *) sym->def = v2; 
     break;
 
     /* some constants have value in a2, some in *a1.p, strange. */
@@ -766,6 +749,10 @@ interpret(struct f_inst *what)
       return res;
     res.type &= ~T_RETURN;    
     break;
+  case P('c','v'):     /* Clear local variables */
+    for (sym = what->a1.p; sym != NULL; sym = sym->aux2)
+      ((struct f_val *) sym->def)->type = T_VOID;
+    break;
   case P('S','W'):
     ONEARG;
     {
@@ -948,6 +935,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
               return 0; 
             f2->a2.p = f1->a2.p;
             break;
+  case P('c','v'): break; /* internal instruction */ 
   case P('S','W'): ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
   case P('i','M'): TWOARGS; break;
   case P('A','p'): TWOARGS; break;
index 395699b0f8b549763ef7bf0045423b1eb6ce58ff..8eeb5c355426cbf4a37e2d1771fde3577f36919d 100644 (file)
@@ -75,7 +75,7 @@ clist l;
        p2 = prepend( p2, 1 );
        print "Should be true: ", p2 ~ pm1, " ", p2, " ", pm1;
 
-       l = - empty -;
+#      l = - empty -;
        l = add( l, (1,2) );
        l = add( l, (2,3) );
        print "Community list (1,2) (2,3) ", l;
@@ -124,6 +124,14 @@ function test_pxset(prefix set pxs)
                                        11.0.0.0/10 ~ pxs, ",", 20.1.0.0/26 ~ pxs;
 }
 
+function test_undef(int a)
+int b;
+{
+       if a = 3
+       then b = 4;
+       print "Defined: ", a, " ", b, " ", defined(b);
+}
+
 function __startup() 
 int i;
 bool b;
@@ -218,6 +226,10 @@ string s;
 
        print "1.2.3.4 = ", onetwo;
 
+       test_undef(2);
+       test_undef(3);
+       test_undef(2);
+
        print "done";
        quitbird;
 #      print "*** FAIL: this is unreachable";