diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-08-28 09:50:44 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-08-28 09:50:44 -0700 |
commit | 0b8eb423973d7e2ebb15c4a6b18befdfe6b23692 (patch) | |
tree | 86e1cb10c42e14fd968d5f7a2fb853a520f3c876 /struct.c | |
parent | ab98634ea8992722046ab857ec0eaec7cb024761 (diff) | |
download | txr-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.c | 5 |
1 files changed, 3 insertions, 2 deletions
@@ -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) |