summaryrefslogtreecommitdiffstats
path: root/struct.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-08-28 09:50:44 -0700
committerKaz Kylheku <kaz@kylheku.com>2016-08-28 09:50:44 -0700
commit0b8eb423973d7e2ebb15c4a6b18befdfe6b23692 (patch)
tree86e1cb10c42e14fd968d5f7a2fb853a520f3c876 /struct.c
parentab98634ea8992722046ab857ec0eaec7cb024761 (diff)
downloadtxr-0b8eb423973d7e2ebb15c4a6b18befdfe6b23692.tar.gz
txr-0b8eb423973d7e2ebb15c4a6b18befdfe6b23692.tar.bz2
txr-0b8eb423973d7e2ebb15c4a6b18befdfe6b23692.zip
Fix runaway recursion in lazy struct initialization.
Staci-blowing test case: (defstruct foo nil bar) (mlet ((f (lnew foo bar (not f.bar)))) (prinl f.bar)) * struct.c (lazy_struct_init): Do not flip the lazy flag to zero here. The problem is that it's being done after the funcall(so->slot[0]), and so the struct is still marked for lazy initialization while that function is running. We could detect the circularity (as done in the force function) but that would create inflexibilities in lazy struct initialization. (check_init_lazy_struct): Flip the lazy flag to zero in this function before calling lazy_struct_init. * txr.1: Document behavior of struct being freely accessible during lazy initialization.
Diffstat (limited to 'struct.c')
-rw-r--r--struct.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/struct.c b/struct.c
index 2075b42f..77e57c2e 100644
--- a/struct.c
+++ b/struct.c
@@ -436,7 +436,6 @@ static void lazy_struct_init(val sinst, struct struct_inst *si)
val cell = funcall(si->slot[0]);
cons_bind (plist, args, cell);
- si->lazy = 0;
si->slot[0] = nil;
if (args && !st->boactor) {
@@ -471,8 +470,10 @@ static void lazy_struct_init(val sinst, struct struct_inst *si)
INLINE void check_init_lazy_struct(val sinst, struct struct_inst *si)
{
- if (si->lazy)
+ if (si->lazy) {
+ si->lazy = 0;
lazy_struct_init(sinst, si);
+ }
}
val make_lazy_struct(val type, val argfun)