Clear local variables in filters and functions.

Fixes crash when used uninitialized variables.
This problem was surprisingly tricky to fix.
This commit is contained in:
Ondrej Zajicek 2010-03-19 09:41:18 +01:00
parent 74e9331fe0
commit aa46124804
3 changed files with 30 additions and 23 deletions

View file

@ -172,6 +172,13 @@ function_params:
function_body: function_body:
decls '{' cmds '}' { decls '{' cmds '}' {
if ($1) {
/* Prepend instruction to clear local variables */
$$ = f_new_inst();
$$->code = P('c','v');
$$->a1.p = $1;
$$->next = $3;
} else
$$ = $3; $$ = $3;
} }
; ;

View file

@ -473,28 +473,11 @@ interpret(struct f_inst *what)
case 's': case 's':
ARG(v2, a2.p); ARG(v2, a2.p);
sym = what->a1.p; sym = what->a1.p;
switch (res.type = v2.type) { if ((sym->class != (SYM_VARIABLE | v2.type)) &&
case T_VOID: runtime( "Can't assign void values" ); (v2.type != T_VOID))
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" ); runtime( "Assigning to variable of incompatible type" );
* (struct f_val *) sym->def = v2; * (struct f_val *) sym->def = v2;
break; break;
default:
bug( "Set to invalid type" );
}
break;
/* some constants have value in a2, some in *a1.p, strange. */ /* some constants have value in a2, some in *a1.p, strange. */
case 'c': /* integer (or simple type) constant, string, set, or prefix_set */ case 'c': /* integer (or simple type) constant, string, set, or prefix_set */
@ -766,6 +749,10 @@ interpret(struct f_inst *what)
return res; return res;
res.type &= ~T_RETURN; res.type &= ~T_RETURN;
break; 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'): case P('S','W'):
ONEARG; ONEARG;
{ {
@ -948,6 +935,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
return 0; return 0;
f2->a2.p = f1->a2.p; f2->a2.p = f1->a2.p;
break; 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('S','W'): ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
case P('i','M'): TWOARGS; break; case P('i','M'): TWOARGS; break;
case P('A','p'): TWOARGS; break; case P('A','p'): TWOARGS; break;

View file

@ -75,7 +75,7 @@ clist l;
p2 = prepend( p2, 1 ); p2 = prepend( p2, 1 );
print "Should be true: ", p2 ~ pm1, " ", p2, " ", pm1; print "Should be true: ", p2 ~ pm1, " ", p2, " ", pm1;
l = - empty -; # l = - empty -;
l = add( l, (1,2) ); l = add( l, (1,2) );
l = add( l, (2,3) ); l = add( l, (2,3) );
print "Community list (1,2) (2,3) ", l; 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; 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() function __startup()
int i; int i;
bool b; bool b;
@ -218,6 +226,10 @@ string s;
print "1.2.3.4 = ", onetwo; print "1.2.3.4 = ", onetwo;
test_undef(2);
test_undef(3);
test_undef(2);
print "done"; print "done";
quitbird; quitbird;
# print "*** FAIL: this is unreachable"; # print "*** FAIL: this is unreachable";