Skip to content
Open
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
5 changes: 5 additions & 0 deletions src/quic/application.cc
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,11 @@ class DefaultApplication final : public Session::Application {
// during the onstream callback (via MakeCallback re-entrancy).
return false;
}

// The stream was created, but was immediately destroyed because there's no onstream handler.
if (stream->is_destroyed()) [[unlikely]] {
return true;
}
} else {
stream = BaseObjectPtr<Stream>(Stream::From(stream_user_data));
if (!stream) {
Expand Down
4 changes: 2 additions & 2 deletions src/quic/session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -860,11 +860,11 @@ struct Session::Impl final : public MemoryRetainer {
}
}

endpoint->RemoveSession(config_.scid, remote_address_);

auto& binding = BindingData::Get(env());
if (stats_slot_) GetSessionStatsArena(binding).ReleaseSlot(stats_slot_);
if (state_slot_) GetSessionStateArena(binding).ReleaseSlot(state_slot_);

endpoint->RemoveSession(config_.scid, remote_address_);
}

void MemoryInfo(MemoryTracker* tracker) const override {
Expand Down
4 changes: 4 additions & 0 deletions src/quic/streams.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1325,6 +1325,10 @@ bool Stream::is_pending() const {
return state()->pending;
}

bool Stream::is_destroyed() const {
return stats()->destroyed_at != 0;
}

stream_id Stream::id() const {
return state()->id;
}
Expand Down
3 changes: 3 additions & 0 deletions src/quic/streams.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,9 @@ class Stream final : public AsyncWrap,
// to be created.
bool is_pending() const;

// True if the stream is already destroyed.
bool is_destroyed() const;

// True if we've completely sent all outbound data for this stream.
// Importantly, this does not necessarily mean that we are completely
// done with the outbound data. We may still be waiting on outbound
Expand Down
47 changes: 47 additions & 0 deletions test/parallel/test-quic-stream-uni-no-onstream.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Flags: --experimental-quic --no-warnings
// Test: client-initiated unidirectional stream with no onstream
// The client creates a uni stream with no onstream.
// Verify that this causes no crash.

import {hasQuic, skip, mustCall} from '../common/index.mjs';

Check failure on line 6 in test/parallel/test-quic-stream-uni-no-onstream.mjs

View workflow job for this annotation

GitHub Actions / lint-js-and-md

A space is required before '}'

Check failure on line 6 in test/parallel/test-quic-stream-uni-no-onstream.mjs

View workflow job for this annotation

GitHub Actions / lint-js-and-md

A space is required after '{'
import {createPrivateKey} from 'node:crypto';

Check failure on line 7 in test/parallel/test-quic-stream-uni-no-onstream.mjs

View workflow job for this annotation

GitHub Actions / lint-js-and-md

A space is required before '}'

Check failure on line 7 in test/parallel/test-quic-stream-uni-no-onstream.mjs

View workflow job for this annotation

GitHub Actions / lint-js-and-md

A space is required after '{'
import * as fixtures from '../common/fixtures.mjs';

const {readKey} = fixtures;

Check failure on line 10 in test/parallel/test-quic-stream-uni-no-onstream.mjs

View workflow job for this annotation

GitHub Actions / lint-js-and-md

A space is required before '}'

Check failure on line 10 in test/parallel/test-quic-stream-uni-no-onstream.mjs

View workflow job for this annotation

GitHub Actions / lint-js-and-md

A space is required after '{'

if (!hasQuic) {
skip('QUIC is not enabled');
}

const {listen, connect} = await import('../common/quic.mjs');

Check failure on line 16 in test/parallel/test-quic-stream-uni-no-onstream.mjs

View workflow job for this annotation

GitHub Actions / lint-js-and-md

A space is required before '}'

Check failure on line 16 in test/parallel/test-quic-stream-uni-no-onstream.mjs

View workflow job for this annotation

GitHub Actions / lint-js-and-md

A space is required after '{'

const serverKey = createPrivateKey(readKey('agent1-key.pem'));
const serverCert = readKey('agent1-cert.pem');

const done = Promise.withResolvers();

const serverEndpoint = await listen(mustCall(async (session) => {
await session.opened;
done.resolve();
}), {
sni: { '*': { keys: [serverKey], certs: [serverCert] } },
alpn: ['repro'],
});

const clientSession = await connect(serverEndpoint.address, {
servername: 'localhost',
alpn: 'repro',
ca: serverCert,
});

await clientSession.opened;

await clientSession.createUnidirectionalStream({
body: 'something something darkside',
});

await done.promise;

await clientSession.close();

await serverEndpoint.close();
Loading