diff --git a/src/quic/data.cc b/src/quic/data.cc index 90e97aa8d0d09f..dc88378144aa36 100644 --- a/src/quic/data.cc +++ b/src/quic/data.cc @@ -115,6 +115,29 @@ Maybe Store::From(Local view, Local detach_key) { return Just(Store(std::move(backing), length, offset)); } +Store Store::CopyFrom(Local buffer) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + auto backing = buffer->GetBackingStore(); + auto length = buffer->ByteLength(); + auto dest = ArrayBuffer::NewBackingStore( + isolate, length, v8::BackingStoreInitializationMode::kUninitialized); + // copy content + memcpy(dest->Data(), backing->Data(), length); + return Store(std::move(dest), length, 0); +} + +Store Store::CopyFrom(Local view) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + auto backing = view->Buffer()->GetBackingStore(); + auto length = view->ByteLength(); + auto offset = view->ByteOffset(); + auto dest = ArrayBuffer::NewBackingStore( + isolate, length, v8::BackingStoreInitializationMode::kUninitialized); + // copy content + memcpy(dest->Data(), static_cast(backing->Data()) + offset, length); + return Store(std::move(dest), length, 0); +} + Local Store::ToUint8Array(Environment* env) const { return !store_ ? Uint8Array::New(ArrayBuffer::New(env->isolate(), 0), 0, 0) diff --git a/src/quic/data.h b/src/quic/data.h index df30c8b4f302e9..bd974ac0c8ba0a 100644 --- a/src/quic/data.h +++ b/src/quic/data.h @@ -70,6 +70,14 @@ class Store final : public MemoryRetainer { v8::Local view, v8::Local detach_key = v8::Local()); + // Creates a Store from the contents of an ArrayBuffer, always copying the + // content. + static Store CopyFrom(v8::Local buffer); + + // Creates a Store from the contents of an ArrayBufferView, always copying the + // content. + static Store CopyFrom(v8::Local view); + v8::Local ToUint8Array(Environment* env) const; inline v8::Local ToUint8Array(Realm* realm) const { return ToUint8Array(realm->env()); diff --git a/src/quic/endpoint.cc b/src/quic/endpoint.cc index 1edbfe8f32cc37..bd3c15d41bb458 100644 --- a/src/quic/endpoint.cc +++ b/src/quic/endpoint.cc @@ -154,10 +154,7 @@ bool SetOption(Environment* env, env, "The %s option must be an ArrayBufferView", nameStr); return false; } - Store store; - if (!Store::From(value.As()).To(&store)) { - return false; - } + Store store = Store::CopyFrom(value.As()); if (store.length() != TokenSecret::QUIC_TOKENSECRET_LEN) { Utf8Value nameStr(env->isolate(), name); THROW_ERR_INVALID_ARG_VALUE( diff --git a/src/quic/tlscontext.cc b/src/quic/tlscontext.cc index 7e7c286b135893..9d585f6fc050a4 100644 --- a/src/quic/tlscontext.cc +++ b/src/quic/tlscontext.cc @@ -133,16 +133,10 @@ bool SetOption(Environment* env, } } else if constexpr (std::is_same::value) { if (item->IsArrayBufferView()) { - Store store; - if (!Store::From(item.As()).To(&store)) { - return false; - } + Store store = Store::CopyFrom(item.As()); (options->*member).push_back(std::move(store)); } else if (item->IsArrayBuffer()) { - Store store; - if (!Store::From(item.As()).To(&store)) { - return false; - } + Store store = Store::CopyFrom(item.As()); (options->*member).push_back(std::move(store)); } else { Utf8Value namestr(env->isolate(), name); @@ -168,16 +162,10 @@ bool SetOption(Environment* env, } } else if constexpr (std::is_same::value) { if (value->IsArrayBufferView()) { - Store store; - if (!Store::From(value.As()).To(&store)) { - return false; - } + Store store = Store::CopyFrom(value.As()); (options->*member).push_back(std::move(store)); } else if (value->IsArrayBuffer()) { - Store store; - if (!Store::From(value.As()).To(&store)) { - return false; - } + Store store = Store::CopyFrom(value.As()); (options->*member).push_back(std::move(store)); } else { Utf8Value namestr(env->isolate(), name); diff --git a/test/parallel/test-quic-handshake-ipv6-only.mjs b/test/parallel/test-quic-handshake-ipv6-only.mjs index fe051b467a201e..8e0ee08c30c83a 100644 --- a/test/parallel/test-quic-handshake-ipv6-only.mjs +++ b/test/parallel/test-quic-handshake-ipv6-only.mjs @@ -47,6 +47,8 @@ const serverEndpoint = await listen(mustCall((serverSession) => { }, ipv6Only: true, } }); +// Buffer is not detached. +assert.strictEqual(certs.buffer.detached, false); // The server must have an address to connect to after listen resolves. assert.ok(serverEndpoint.address !== undefined); diff --git a/test/parallel/test-quic-handshake.mjs b/test/parallel/test-quic-handshake.mjs index ed581c32e34788..c0097a2cf9bffd 100644 --- a/test/parallel/test-quic-handshake.mjs +++ b/test/parallel/test-quic-handshake.mjs @@ -38,6 +38,9 @@ const serverEndpoint = await listen(mustCall((serverSession) => { }).then(mustCall()); }), { keys, certs }); +// Buffer is not detached. +assert.strictEqual(certs.buffer.detached, false); + // The server must have an address to connect to after listen resolves. assert.ok(serverEndpoint.address !== undefined); diff --git a/test/parallel/test-quic-internal-endpoint-listen-defaults.mjs b/test/parallel/test-quic-internal-endpoint-listen-defaults.mjs index ef20e8253ab26e..1b5eecc7b92276 100644 --- a/test/parallel/test-quic-internal-endpoint-listen-defaults.mjs +++ b/test/parallel/test-quic-internal-endpoint-listen-defaults.mjs @@ -28,15 +28,23 @@ assert.strictEqual(endpoint.address, undefined); await assert.rejects(listen(123, { keys, certs, endpoint }), { code: 'ERR_INVALID_ARG_TYPE', }); +// Buffer is not detached. +assert.strictEqual(certs.buffer.detached, false); await assert.rejects(listen(() => {}, 123), { code: 'ERR_INVALID_ARG_TYPE', }); await listen(() => {}, { keys, certs, endpoint }); +// Buffer is not detached. +assert.strictEqual(certs.buffer.detached, false); + await assert.rejects(listen(() => {}, { keys, certs, endpoint }), { code: 'ERR_INVALID_STATE', }); +// Buffer is not detached. +assert.strictEqual(certs.buffer.detached, false); + assert.ok(state.isBound); assert.ok(state.isReceiving); assert.ok(state.isListening); @@ -58,6 +66,9 @@ assert.ok(endpoint.destroyed); await assert.rejects(listen(() => {}, { keys, certs, endpoint }), { code: 'ERR_INVALID_STATE', }); +// Buffer is not detached. +assert.strictEqual(certs.buffer.detached, false); + assert.throws(() => { endpoint.busy = true; }, { code: 'ERR_INVALID_STATE', });