Skip to content

Re-land the fix and regression test for vuln-187 - #6934

Merged
harrishancock merged 1 commit into
mainfrom
harris/2026-08-07-reland-vuln-187
Aug 7, 2026
Merged

Re-land the fix and regression test for vuln-187#6934
harrishancock merged 1 commit into
mainfrom
harris/2026-08-07-reland-vuln-187

Conversation

@harrishancock

Copy link
Copy Markdown
Collaborator

A draining read delivers its result to pumpToImpl through a kj event, and runs the stream's pull() callback along the way. A pull() that aborts the request's signal makes the canceler destroy the pump's coroutine frame from inside that event, so the event is destroyed while still firing and kj aborts the process with "Promise callback destroyed itself".

Neither isolate-lock round trip in the pump is awaited directly any more. Each is handed to the IoContext's task set, and the pump awaits an unrelated fulfiller, so dropping the pump destroys only that await and leaves the firing event to be unwound by its new owner.

Those tasks outlive the coroutine frame, so they reach the DrainingReader through a kj::Weak rather than the frame-owned kj::Own. Without that, the read lambda would run against a freed reader whenever the pump is dropped before the isolate lock is acquired.

The fix originally landed as 00e86e1 and was swept away by 4447562, a wholesale revert of the streams-cleanup-investigation merge. That first version captured the reader by reference, which is what the kj::Weak above replaces; this follows the later 2de66f75e, which had corrected it. Both are James's, as is the third attempt, f3f408768, which drops the code change and keeps only the test — not an option here, since the abort still reproduces without it.

The surrounding tree has moved on twice over: the draining read is no longer autogated, so the test needs no gate, and DrainingReader is a kj::PtrTarget, so the weak pointer comes from addWeakToThis() rather than a hand-rolled cell.

Assisted-by: OpenCode:claude-opus-5

A draining read delivers its result to pumpToImpl through a kj event, and
runs the stream's pull() callback along the way. A pull() that aborts the
request's signal makes the canceler destroy the pump's coroutine frame
from inside that event, so the event is destroyed while still firing and
kj aborts the process with "Promise callback destroyed itself".

Neither isolate-lock round trip in the pump is awaited directly any
more. Each is handed to the IoContext's task set, and the pump awaits an
unrelated fulfiller, so dropping the pump destroys only that await and
leaves the firing event to be unwound by its new owner.

Those tasks outlive the coroutine frame, so they reach the
DrainingReader through a kj::Weak rather than the frame-owned kj::Own.
Without that, the read lambda would run against a freed reader whenever
the pump is dropped before the isolate lock is acquired.

The fix originally landed as 00e86e1 and was swept away by 4447562,
a wholesale revert of the streams-cleanup-investigation merge. That first
version captured the reader by reference, which is what the kj::Weak
above replaces; this follows the later 2de66f75e, which had corrected it.
Both are James's, as is the third attempt, f3f408768, which drops the
code change and keeps only the test — not an option here, since the abort
still reproduces without it.

The surrounding tree has moved on twice over: the draining read is no
longer autogated, so the test needs no gate, and DrainingReader is a
kj::PtrTarget, so the weak pointer comes from addWeakToThis() rather than
a hand-rolled cell.

Co-authored-by: James M Snell <jsnell@cloudflare.com>
Assisted-by: OpenCode:claude-opus-5
@harrishancock
harrishancock requested review from a team as code owners August 7, 2026 20:56
@ask-bonk

ask-bonk Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

LGTM

github run

@harrishancock
harrishancock merged commit a861db3 into main Aug 7, 2026
25 checks passed
@harrishancock
harrishancock deleted the harris/2026-08-07-reland-vuln-187 branch August 7, 2026 22:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants