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:
parent
74e9331fe0
commit
aa46124804
3 changed files with 30 additions and 23 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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";
|
||||||
|
|
Loading…
Reference in a new issue