From 0b8eb423973d7e2ebb15c4a6b18befdfe6b23692 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Sun, 28 Aug 2016 09:50:44 -0700 Subject: 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. --- struct.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'struct.c') 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) -- cgit v1.2.3