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
commit68811c68c7342d7307b684313962edd105b88a83 (patch)
tree794093b25c85ad4f9a369a63cbeb205832f80135
parentb67f0c623feb14ff27e1c70ef192163dd31b8945 (diff)
downloadtxr-68811c68c7342d7307b684313962edd105b88a83.tar.gz
txr-68811c68c7342d7307b684313962edd105b88a83.tar.bz2
txr-68811c68c7342d7307b684313962edd105b88a83.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"),