mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2026-04-30 19:09:26 +08:00
* Fix #635: Segfault in async result via dangling pointer from optimized for loop * The optimized for loop (chaiscript_optimizer.hpp) stored the loop counter as a stack-local `int` and exposed it to ChaiScript via `var(&i)`, creating a reference-type Boxed_Value pointing to the stack frame.
This commit is contained in:
parent
5a6050210d
commit
07d62aae99
@ -295,6 +295,7 @@ list(SORT UNIT_TESTS)
|
|||||||
if(NOT MULTITHREAD_SUPPORT_ENABLED)
|
if(NOT MULTITHREAD_SUPPORT_ENABLED)
|
||||||
list(REMOVE_ITEM UNIT_TESTS
|
list(REMOVE_ITEM UNIT_TESTS
|
||||||
async_engine_lifetime.chai
|
async_engine_lifetime.chai
|
||||||
|
async_return_value.chai
|
||||||
future.chai
|
future.chai
|
||||||
list_push_front.chai
|
list_push_front.chai
|
||||||
move_async.chai
|
move_async.chai
|
||||||
|
|||||||
@ -397,8 +397,9 @@ namespace chaiscript {
|
|||||||
assert(children.size() == 1);
|
assert(children.size() == 1);
|
||||||
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
||||||
|
|
||||||
int i = start_int;
|
Boxed_Value bv_i(start_int);
|
||||||
t_ss.add_object(id, var(&i));
|
auto &i = *static_cast<int *>(bv_i.get_ptr());
|
||||||
|
t_ss.add_object(id, bv_i);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (; i < end_int; ++i) {
|
for (; i < end_int; ++i) {
|
||||||
|
|||||||
41
unittests/assign_no_aliasing.chai
Normal file
41
unittests/assign_no_aliasing.chai
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// Issue #635: optimized for loop with := must not produce dangling values
|
||||||
|
// := is reference-assign, so ret aliases i and sees the loop exit value
|
||||||
|
|
||||||
|
// Basic: capture loop variable via :=
|
||||||
|
var ret = 0
|
||||||
|
for (var i = 0; i < 100; ++i) {
|
||||||
|
ret := i
|
||||||
|
}
|
||||||
|
assert_equal(100, ret)
|
||||||
|
|
||||||
|
// Return from function containing optimized for loop
|
||||||
|
def loop_result() {
|
||||||
|
var ret = 0
|
||||||
|
for (var i = 0; i < 200; ++i) {
|
||||||
|
ret := i
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
assert_equal(200, loop_result())
|
||||||
|
|
||||||
|
// Multiple calls return consistent results
|
||||||
|
assert_equal(loop_result(), loop_result())
|
||||||
|
|
||||||
|
// Nested optimized for loops
|
||||||
|
var outer_val = 0
|
||||||
|
var inner_val = 0
|
||||||
|
for (var i = 0; i < 10; ++i) {
|
||||||
|
for (var j = 0; j < 10; ++j) {
|
||||||
|
inner_val := j
|
||||||
|
}
|
||||||
|
outer_val := i
|
||||||
|
}
|
||||||
|
assert_equal(10, outer_val)
|
||||||
|
assert_equal(10, inner_val)
|
||||||
|
|
||||||
|
// Value-assign (=) captures last body-iteration value, not exit value
|
||||||
|
var ret2 = 0
|
||||||
|
for (var i = 0; i < 100; ++i) {
|
||||||
|
ret2 = i
|
||||||
|
}
|
||||||
|
assert_equal(99, ret2)
|
||||||
25
unittests/async_return_value.chai
Normal file
25
unittests/async_return_value.chai
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Issue #635: async + optimized for loop must not segfault from dangling pointer
|
||||||
|
// := is reference-assign, so ret aliases i and sees the loop exit value
|
||||||
|
|
||||||
|
var func = fun(){
|
||||||
|
var ret = 0;
|
||||||
|
for (var i = 0; i < 1000; ++i) {
|
||||||
|
ret := i;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
var&fut1 = async(func);
|
||||||
|
var fut2 = async(func);
|
||||||
|
|
||||||
|
assert_equal(1000, fut1.get())
|
||||||
|
assert_equal(1000, fut2.get())
|
||||||
|
|
||||||
|
// Multiple concurrent async calls to stress the scenario
|
||||||
|
var results = []
|
||||||
|
for (var n = 0; n < 5; ++n) {
|
||||||
|
results.push_back(async(func))
|
||||||
|
}
|
||||||
|
for (var n = 0; n < 5; ++n) {
|
||||||
|
assert_equal(1000, results[n].get())
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user