summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-10-20 07:00:03 -0700
committerKaz Kylheku <kaz@kylheku.com>2016-10-20 07:00:03 -0700
commit2b0ddbf1ab3a710a362997fb6ed6c4f3fe5d08e0 (patch)
tree794093b25c85ad4f9a369a63cbeb205832f80135
parent832a87947f9d25c08c10bf6fa7c2ef2d21a82770 (diff)
downloadtxr-2b0ddbf1ab3a710a362997fb6ed6c4f3fe5d08e0.tar.gz
txr-2b0ddbf1ab3a710a362997fb6ed6c4f3fe5d08e0.tar.bz2
txr-2b0ddbf1ab3a710a362997fb6ed6c4f3fe5d08e0.zip
Check call graph circularity in circ_backpatch.
The circ_backpatch function could suffer runaway recursion, so we must add a cycle check. This could happen due to hitting cyclical objects when traversing structs. Structs have static slots that could contain cyclic objects, as well as construction logic which can generate slots that contain cycles and are not overridden by anything in the literal. * parser.c (circ_backpatch): Take struct circ_stack * argument; extend the circ_stack in recursive calls. Do circular check on entry. (parser_resolve_circ): Pass null pointer as the new stack argument to circ_backpatch.
-rw-r--r--parser.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/parser.c b/parser.c
index bb023343..cd542fe8 100644
--- a/parser.c
+++ b/parser.c
@@ -234,8 +234,13 @@ static val patch_ref(parser_t *p, val obj)
return nil;
}
-static void circ_backpatch(parser_t *p, val obj)
+static void circ_backpatch(parser_t *p, struct circ_stack *up, val obj)
{
+ struct circ_stack cs = { up, obj };
+
+ if (!parser_callgraph_circ_check(up, obj))
+ return;
+
tail:
if (!p->circ_count)
return;
@@ -252,7 +257,7 @@ tail:
if (ra)
rplaca(obj, ra);
else
- circ_backpatch(p, a);
+ circ_backpatch(p, &cs, a);
if (rd) {
rplacd(obj, rd);
@@ -274,7 +279,7 @@ tail:
if (rv)
set(vecref_l(obj, in), rv);
else
- circ_backpatch(p, v);
+ circ_backpatch(p, &cs, v);
if (!p->circ_count)
break;
}
@@ -291,7 +296,7 @@ tail:
if (rs)
set_from(obj, rs);
else
- circ_backpatch(p, s);
+ circ_backpatch(p, &cs, s);
if (re) {
set_to(obj, re);
@@ -311,7 +316,7 @@ tail:
val iter = hash_begin(obj);
val cell;
while ((cell = hash_next(iter)))
- circ_backpatch(p, cell);
+ circ_backpatch(p, &cs, cell);
}
} else if (structp(obj)) {
val stype = struct_type(obj);
@@ -324,7 +329,7 @@ tail:
if (rsv)
slotset(obj, sn, rsv);
else
- circ_backpatch(p, sv);
+ circ_backpatch(p, &cs, sv);
}
}
break;
@@ -339,7 +344,8 @@ void parser_resolve_circ(parser_t *p)
if (p->circ_count == 0)
return;
- circ_backpatch(p, p->syntax_tree);
+
+ circ_backpatch(p, 0, p->syntax_tree);
if (p->circ_count > 0)
yyerrorf(p->scanner, lit("not all #<num># refs replaced in object ~s"),