Commit 059c8012e67 for nodejs

commit 059c8012e6793561d5e3440802a4542020e86aed
Author: Matteo Collina <hello@matteocollina.com>
Date:   Sun Nov 1 16:20:38 2026 +0100

    http2: avoid overflowing ALTSVC buffers

    Http2Session::AltSvc allocated origin and field-value buffers at their
    exact lengths but requested V8 to append a null terminator. This wrote
    one byte past heap-backed buffers.

    nghttp2_submit_altsvc() consumes explicit lengths and makes its own
    terminated copies. Write only the string contents.

    Assisted-by: OpenAI Codex
    Signed-off-by: Matteo Collina <hello@matteocollina.com>
    PR-URL: https://github.com/nodejs-private/node-private/pull/1035
    Reviewed-By: Tim Perry <pimterry@gmail.com>
    CVE-ID: CVE-2026-123828

diff --git a/src/node_http2.cc b/src/node_http2.cc
index a6779610ddb..9a7d700e046 100644
--- a/src/node_http2.cc
+++ b/src/node_http2.cc
@@ -3371,13 +3371,8 @@ void Http2Session::AltSvc(const FunctionCallbackInfo<Value>& args) {

   MaybeStackBuffer<uint8_t> origin(origin_len);
   MaybeStackBuffer<uint8_t> value(value_len);
-  origin_str->WriteOneByteV2(env->isolate(),
-                             0,
-                             origin_len,
-                             *origin,
-                             String::WriteFlags::kNullTerminate);
-  value_str->WriteOneByteV2(
-      env->isolate(), 0, value_len, *value, String::WriteFlags::kNullTerminate);
+  origin_str->WriteOneByteV2(env->isolate(), 0, origin_len, *origin);
+  value_str->WriteOneByteV2(env->isolate(), 0, value_len, *value);

   session->AltSvc(id, *origin, origin_len, *value, value_len);
 }
diff --git a/test/parallel/test-http2-altsvc.js b/test/parallel/test-http2-altsvc.js
index c5abfc33265..de2a3557040 100644
--- a/test/parallel/test-http2-altsvc.js
+++ b/test/parallel/test-http2-altsvc.js
@@ -8,6 +8,9 @@ const assert = require('assert');
 const http2 = require('http2');
 const Countdown = require('../common/countdown');

+const longOrigin = `https://${'a'.repeat(1040)}`;
+const longAlt = `h2=":${'8'.repeat(1042)}"`;
+
 const server = http2.createServer();
 server.on('stream', common.mustCall((stream) => {
   stream.session.altsvc('h2=":8000"', stream.id);
@@ -22,6 +25,8 @@ server.on('session', common.mustCall((session) => {
   session.altsvc('h2=":8000"', 'https://example.org:8111/this');
   session.altsvc('h2=":8000"', new URL('https://example.org:8111/this'));
   session.altsvc('h2=":8000"', { origin: 'https://example.org:8111' });
+  session.altsvc('h2=":8001"', longOrigin);
+  session.altsvc(longAlt, 'https://example.org:8112');

   // Won't error, but won't send anything because the stream does not exist
   session.altsvc('h2=":8000"', 3);
@@ -104,25 +109,33 @@ server.on('session', common.mustCall((session) => {
 server.listen(0, common.mustCall(() => {
   const client = http2.connect(`http://localhost:${server.address().port}`);

-  const countdown = new Countdown(4, () => {
+  const countdown = new Countdown(6, () => {
     client.close();
     server.close();
   });

   client.on('altsvc', common.mustCall((alt, origin, stream) => {
-    assert.strictEqual(alt, 'h2=":8000"');
-    switch (stream) {
-      case 0:
-        assert.strictEqual(origin, 'https://example.org:8111');
-        break;
-      case 1:
-        assert.strictEqual(origin, '');
-        break;
-      default:
-        assert.fail('should not happen');
+    if (alt === 'h2=":8001"') {
+      assert.strictEqual(origin, longOrigin);
+      assert.strictEqual(stream, 0);
+    } else if (alt === longAlt) {
+      assert.strictEqual(origin, 'https://example.org:8112');
+      assert.strictEqual(stream, 0);
+    } else {
+      assert.strictEqual(alt, 'h2=":8000"');
+      switch (stream) {
+        case 0:
+          assert.strictEqual(origin, 'https://example.org:8111');
+          break;
+        case 1:
+          assert.strictEqual(origin, '');
+          break;
+        default:
+          assert.fail('should not happen');
+      }
     }
     countdown.dec();
-  }, 4));
+  }, 6));

   const req = client.request();
   req.resume();