Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix dangling pointer in coroutine yield() #2332

Merged
merged 1 commit into from
Jun 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions releases/releases.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1370,3 +1370,4 @@ duktape_releases:
- "Fix unsafe behavior in JSON.stringify() when replacer argument is an array and Array.prototype has inherited index properties (GH-2202, GH-2324)"
- "Fix RegExp exec() result object creation bug when Array.prototype has index properties (GH-2203, GH-2325)"
- "Fix Proxy 'ownKeys' trap postprocessing bug when Array.prototype has index properties (GH-2207, GH-2326)"
- "Fix coroutine yield() dangling pointer when the yielding coroutine is no longer reachable except via the resume/yield relationship (GH-2204, GH-2332)"
14 changes: 9 additions & 5 deletions src-input/duk_js_executor.c
Original file line number Diff line number Diff line change
Expand Up @@ -1309,17 +1309,21 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation
DUK_DD(DUK_DDPRINT("-> yield an error, converted to a throw in the resumer, propagate"));
goto check_longjmp;
} else {
duk_hthread_activation_unwind_norz(resumer);
duk__handle_yield(thr, resumer, &thr->heap->lj.value1);
/* When handling the yield, the last reference to
* 'thr' may disappear.
*/

DUK_GC_TORTURE(resumer->heap);
duk_hthread_activation_unwind_norz(resumer);
DUK_GC_TORTURE(resumer->heap);
thr->state = DUK_HTHREAD_STATE_YIELDED;
thr->resumer = NULL;
DUK_HTHREAD_DECREF_NORZ(thr, resumer);
resumer->state = DUK_HTHREAD_STATE_RUNNING;
DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
#if 0
thr = resumer; /* not needed, as we exit right away */
#endif
duk__handle_yield(thr, resumer, &thr->heap->lj.value1);
thr = resumer;
DUK_GC_TORTURE(resumer->heap);

DUK_DD(DUK_DDPRINT("-> yield a value, restart execution in resumer"));
retval = DUK__LONGJMP_RESTART;
Expand Down
15 changes: 15 additions & 0 deletions tests/ecmascript/test-bug-coroutine-yield-refzero-1-gh2204.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// https://github.com/svaarala/duktape/issues/2204

/*===
0
done
===*/

function yielder() {
var yield = Duktape.Thread.yield;
t = {};
yield(0);
}
var t = Duktape.Thread(yielder);
print(Duktape.Thread.resume(t));
print('done');
17 changes: 17 additions & 0 deletions tests/ecmascript/test-bug-coroutine-yield-refzero-2-gh2204.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*===
RangeError: aiee
done
===*/

function yielder() {
var yield = Duktape.Thread.yield;
t = {};
throw new RangeError('aiee');
}
var t = Duktape.Thread(yielder);
try {
Duktape.Thread.resume(t);
} catch (e) {
print(e);
}
print('done');