diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index e8048eb3..e6d11544 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -397,11 +397,11 @@ namespace chaiscript { assert(children.size() == 1); chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); - int i = start_int; - t_ss.add_object(id, var(&i)); + auto i = std::make_shared(start_int); + t_ss.add_object(id, var(i)); try { - for (; i < end_int; ++i) { + for (; *i < end_int; ++(*i)) { try { // Body of Loop children[0]->eval(t_ss); diff --git a/unittests/future_assign.chai b/unittests/future_assign.chai new file mode 100644 index 00000000..41152169 --- /dev/null +++ b/unittests/future_assign.chai @@ -0,0 +1,21 @@ +// Regression test for #635: Segfault when using := in async function +// with optimized for loop. The := operator copies raw pointers from the +// loop variable, which is stack-allocated in the optimized for loop. +// When the function returns, the stack is unwound and pointers dangle. + +var func = fun(){ + var ret = 0; + for (var i = 0; i < 50000; ++i) { + ret := i; + } + return ret; +} + +var fut1 = async(func); +var fut2 = async(func); + +// This triggers Boxed_Number::get_as on the future results +// which would crash if the pointers are dangling +// := creates an alias, so ret ends up as 50000 (loop exit value of i) +assert_equal(50000, fut1.get()) +assert_equal(50000, fut2.get())