From feb9f7cb53fe27aec146057712fa8262fb2cbb76 Mon Sep 17 00:00:00 2001 From: Bob Nystrom Date: Thu, 24 Apr 2014 17:52:53 -0700 Subject: [PATCH] Fix crash bug in closure capturing. --- src/wren_vm.c | 4 ++-- test/closure/close_over_later_variable.wren | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 test/closure/close_over_later_variable.wren diff --git a/src/wren_vm.c b/src/wren_vm.c index 4bd4cc97..056b253b 100644 --- a/src/wren_vm.c +++ b/src/wren_vm.c @@ -218,7 +218,7 @@ static Upvalue* captureUpvalue(WrenVM* vm, ObjFiber* fiber, int slot) Upvalue* prevUpvalue = NULL; Upvalue* upvalue = fiber->openUpvalues; - // Walk towards the bottom of the stack until we find a previously existsing + // Walk towards the bottom of the stack until we find a previously existing // upvalue or pass where it should be. while (upvalue != NULL && upvalue->value > local) { @@ -227,7 +227,7 @@ static Upvalue* captureUpvalue(WrenVM* vm, ObjFiber* fiber, int slot) } // Found an existing upvalue for this local. - if (upvalue->value == local) return upvalue; + if (upvalue != NULL && upvalue->value == local) return upvalue; // We've walked past this local on the stack, so there must not be an // upvalue for it already. Make a new one and link it in in the right diff --git a/test/closure/close_over_later_variable.wren b/test/closure/close_over_later_variable.wren new file mode 100644 index 00000000..0d3f977a --- /dev/null +++ b/test/closure/close_over_later_variable.wren @@ -0,0 +1,13 @@ +// This is a regression test. There was a bug where if an upvalue for an +// earlier local (here "a") was captured *after* a later one ("b"), then Wren +// would crash because it walked to the end of the upvalue list (correct), but +// then didn't handle not finding the variable. + +new Fn { + var a = "a" + var b = "b" + new Fn { + IO.print(b) // expect: b + IO.print(a) // expect: a + }.call +}.call