diff --git a/CVE-2023-46809.patch b/CVE-2023-46809.patch new file mode 100644 index 0000000000000000000000000000000000000000..af249c3088634191a698714f7fd109be9e4da7e9 --- /dev/null +++ b/CVE-2023-46809.patch @@ -0,0 +1,615 @@ +From: Michael Dawson +Date: Thu, 4 Jan 2024 21:32:51 +0000 +Subject: CVE-2023-46809 crypto: disable PKCS#1 padding for privateDecrypt + +Refs: https://hackerone.com/bugs?subject=nodejs&report_id=2269177 + +Disable RSA_PKCS1_PADDING for crypto.privateDecrypt() in order +to protect against the Marvin attack. + +Includes a security revert flag that can be used to restore +support. + +Signed-off-by: Michael Dawson +bug-github-pull: https://github.com/nodejs-private/node-private/pull/525 +bug-hakerone: https://hackerone.com/bugs?subject=nodejs&report_id=2269177 +bug: https://nodejs.org/en/blog/vulnerability/february-2024-security-releases/#nodejs-is-vulnerable-to-the-marvin-attack-timing-variant-of-the-bleichenbacher-attack-against-pkcs1 +origin: backport, https://github.com/nodejs/node/commit/d3d357ab096884f10f5d2f164149727eea875635 +Reviewed-By: Rafael Gonzaga +Reviewed-By: Matteo Collina +CVE-ID: CVE-2023-46809 +--- + src/node_crypto.cc | 28 ++ + src/node_revert.h | 4 +- + test/parallel/test-crypto-rsa-dsa-revert.js | 466 ++++++++++++++++++++++++++++ + test/parallel/test-crypto-rsa-dsa.js | 42 ++- + 4 files changed, 525 insertions(+), 15 deletions(-) + create mode 100644 test/parallel/test-crypto-rsa-dsa-revert.js + +diff --git a/src/node_crypto.cc b/src/node_crypto.cc +index 6c2a5de..91d52c5 100644 +--- a/src/node_crypto.cc ++++ b/src/node_crypto.cc +@@ -37,6 +37,7 @@ + #include "string_bytes.h" + #include "threadpoolwork-inl.h" + #include "util-inl.h" ++#include "node_revert.h" + #include "v8.h" + + #include +@@ -5111,6 +5112,33 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo& args) { + uint32_t padding; + if (!args[offset + 1]->Uint32Value(env->context()).To(&padding)) return; + ++ if (EVP_PKEY_cipher == EVP_PKEY_decrypt && ++ operation == PublicKeyCipher::kPrivate && padding == RSA_PKCS1_PADDING && ++ !IsReverted(SECURITY_REVERT_CVE_2023_46809)) { ++ EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(pkey.get(), nullptr)); ++ CHECK(ctx); ++ ++ if (EVP_PKEY_decrypt_init(ctx.get()) <= 0) { ++ return ThrowCryptoError(env, ERR_get_error()); ++ } ++ ++ int rsa_pkcs1_implicit_rejection = ++ EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_pkcs1_implicit_rejection", "1"); ++ // From the doc -2 means that the option is not supported. ++ // The default for the option is enabled and if it has been ++ // specifically disabled we want to respect that so we will ++ // not throw an error if the option is supported regardless ++ // of how it is set. The call to set the value ++ // will not affect what is used since a different context is ++ // used in the call if the option is supported ++ if (rsa_pkcs1_implicit_rejection <= 0) { ++ return THROW_ERR_INVALID_ARG_VALUE( ++ env, ++ "RSA_PKCS1_PADDING is no longer supported for private decryption," ++ " this can be reverted with --security-revert=CVE-2023-46809"); ++ } ++ } ++ + const node::Utf8Value oaep_str(env->isolate(), args[offset + 2]); + const char* oaep_hash = args[offset + 2]->IsString() ? *oaep_str : nullptr; + const EVP_MD* digest = nullptr; +diff --git a/src/node_revert.h b/src/node_revert.h +index b95eb0d..c636720 100644 +--- a/src/node_revert.h ++++ b/src/node_revert.h +@@ -22,9 +22,7 @@ namespace node { + XX(CVE_2019_9518, "CVE-2019-9518", "HTTP/2 Empty DATA Frame Flooding") \ + XX(CVE_2021_44531, "CVE-2021-44531", "Cert Verif Bypass via URI SAN") \ + XX(CVE_2021_44532, "CVE-2021-44532", "Cert Verif Bypass via Str Inject") \ +-// XX(CVE_2016_PEND, "CVE-2016-PEND", "Vulnerability Title") +- // TODO(addaleax): Remove all of the above before Node.js 13 as the comment +- // at the start of the file indicates. ++ XX(CVE_2023_46809, "CVE-2023-46809", "Marvin attack on PKCS#1 padding") + + enum reversion { + #define V(code, ...) SECURITY_REVERT_##code, +diff --git a/test/parallel/test-crypto-rsa-dsa-revert.js b/test/parallel/test-crypto-rsa-dsa-revert.js +new file mode 100644 +index 0000000..d40c66f +--- /dev/null ++++ b/test/parallel/test-crypto-rsa-dsa-revert.js +@@ -0,0 +1,466 @@ ++'use strict'; ++// Flags: --security-revert=CVE-2023-46809 ++const common = require('../common'); ++if (!common.hasCrypto) ++ common.skip('missing crypto'); ++ ++const assert = require('assert'); ++const crypto = require('crypto'); ++ ++const constants = crypto.constants; ++ ++const fixtures = require('../common/fixtures'); ++ ++// Test certificates ++const certPem = fixtures.readKey('rsa_cert.crt'); ++const keyPem = fixtures.readKey('rsa_private.pem'); ++const rsaKeySize = 2048; ++const rsaPubPem = fixtures.readKey('rsa_public.pem', 'ascii'); ++const rsaKeyPem = fixtures.readKey('rsa_private.pem', 'ascii'); ++const rsaKeyPemEncrypted = fixtures.readKey('rsa_private_encrypted.pem', ++ 'ascii'); ++const dsaPubPem = fixtures.readKey('dsa_public.pem', 'ascii'); ++const dsaKeyPem = fixtures.readKey('dsa_private.pem', 'ascii'); ++const dsaKeyPemEncrypted = fixtures.readKey('dsa_private_encrypted.pem', ++ 'ascii'); ++const rsaPkcs8KeyPem = fixtures.readKey('rsa_private_pkcs8.pem'); ++const dsaPkcs8KeyPem = fixtures.readKey('dsa_private_pkcs8.pem'); ++ ++const ec = new TextEncoder(); ++ ++const openssl1DecryptError = { ++ message: 'error:06065064:digital envelope routines:EVP_DecryptFinal_ex:' + ++ 'bad decrypt', ++ code: 'ERR_OSSL_EVP_BAD_DECRYPT', ++ reason: 'bad decrypt', ++ function: 'EVP_DecryptFinal_ex', ++ library: 'digital envelope routines', ++}; ++ ++const decryptError = common.hasOpenSSL3 ? ++ { message: 'error:1C800064:Provider routines::bad decrypt' } : ++ openssl1DecryptError; ++ ++const decryptPrivateKeyError = common.hasOpenSSL3 ? { ++ message: 'error:1C800064:Provider routines::bad decrypt', ++} : openssl1DecryptError; ++ ++function getBufferCopy(buf) { ++ return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); ++} ++ ++// Test RSA encryption/decryption ++{ ++ const input = 'I AM THE WALRUS'; ++ const bufferToEncrypt = Buffer.from(input); ++ const bufferPassword = Buffer.from('password'); ++ ++ let encryptedBuffer = crypto.publicEncrypt(rsaPubPem, bufferToEncrypt); ++ ++ // Test other input types ++ let otherEncrypted; ++ { ++ const ab = getBufferCopy(ec.encode(rsaPubPem)); ++ const ab2enc = getBufferCopy(bufferToEncrypt); ++ ++ crypto.publicEncrypt(ec.encode(rsaPubPem), bufferToEncrypt); ++ crypto.publicEncrypt(new Uint8Array(ab), new Uint8Array(ab2enc)); ++ crypto.publicEncrypt(new DataView(ab), new DataView(ab2enc)); ++ otherEncrypted = crypto.publicEncrypt({ ++ key: Buffer.from(ab) ++ }, Buffer.from(ab2enc)); ++ } ++ ++ let decryptedBuffer = crypto.privateDecrypt(rsaKeyPem, encryptedBuffer); ++ const otherDecrypted = crypto.privateDecrypt(rsaKeyPem, otherEncrypted); ++ assert.strictEqual(decryptedBuffer.toString(), input); ++ assert.strictEqual(otherDecrypted.toString(), input); ++ ++ decryptedBuffer = crypto.privateDecrypt(rsaPkcs8KeyPem, encryptedBuffer); ++ assert.strictEqual(decryptedBuffer.toString(), input); ++ ++ let decryptedBufferWithPassword = crypto.privateDecrypt({ ++ key: rsaKeyPemEncrypted, ++ passphrase: 'password' ++ }, encryptedBuffer); ++ ++ const otherDecryptedBufferWithPassword = crypto.privateDecrypt({ ++ key: rsaKeyPemEncrypted, ++ passphrase: ec.encode('password') ++ }, encryptedBuffer); ++ ++ assert.strictEqual( ++ otherDecryptedBufferWithPassword.toString(), ++ decryptedBufferWithPassword.toString()); ++ ++ decryptedBufferWithPassword = crypto.privateDecrypt({ ++ key: rsaKeyPemEncrypted, ++ passphrase: 'password' ++ }, encryptedBuffer); ++ ++ assert.strictEqual(decryptedBufferWithPassword.toString(), input); ++ ++ encryptedBuffer = crypto.publicEncrypt({ ++ key: rsaKeyPemEncrypted, ++ passphrase: 'password' ++ }, bufferToEncrypt); ++ ++ decryptedBufferWithPassword = crypto.privateDecrypt({ ++ key: rsaKeyPemEncrypted, ++ passphrase: 'password' ++ }, encryptedBuffer); ++ assert.strictEqual(decryptedBufferWithPassword.toString(), input); ++ ++ encryptedBuffer = crypto.privateEncrypt({ ++ key: rsaKeyPemEncrypted, ++ passphrase: bufferPassword ++ }, bufferToEncrypt); ++ ++ decryptedBufferWithPassword = crypto.publicDecrypt({ ++ key: rsaKeyPemEncrypted, ++ passphrase: bufferPassword ++ }, encryptedBuffer); ++ assert.strictEqual(decryptedBufferWithPassword.toString(), input); ++ ++ // Now with explicit RSA_PKCS1_PADDING. ++ encryptedBuffer = crypto.privateEncrypt({ ++ padding: crypto.constants.RSA_PKCS1_PADDING, ++ key: rsaKeyPemEncrypted, ++ passphrase: bufferPassword ++ }, bufferToEncrypt); ++ ++ decryptedBufferWithPassword = crypto.publicDecrypt({ ++ padding: crypto.constants.RSA_PKCS1_PADDING, ++ key: rsaKeyPemEncrypted, ++ passphrase: bufferPassword ++ }, encryptedBuffer); ++ assert.strictEqual(decryptedBufferWithPassword.toString(), input); ++ ++ // Omitting padding should be okay because RSA_PKCS1_PADDING is the default. ++ decryptedBufferWithPassword = crypto.publicDecrypt({ ++ key: rsaKeyPemEncrypted, ++ passphrase: bufferPassword ++ }, encryptedBuffer); ++ assert.strictEqual(decryptedBufferWithPassword.toString(), input); ++ ++ // Now with RSA_NO_PADDING. Plaintext needs to match key size. ++ // OpenSSL 3.x has a rsa_check_padding that will cause an error if ++ // RSA_NO_PADDING is used. ++ if (!common.hasOpenSSL3) { ++ { ++ const plaintext = 'x'.repeat(rsaKeySize / 8); ++ encryptedBuffer = crypto.privateEncrypt({ ++ padding: crypto.constants.RSA_NO_PADDING, ++ key: rsaKeyPemEncrypted, ++ passphrase: bufferPassword ++ }, Buffer.from(plaintext)); ++ ++ decryptedBufferWithPassword = crypto.publicDecrypt({ ++ padding: crypto.constants.RSA_NO_PADDING, ++ key: rsaKeyPemEncrypted, ++ passphrase: bufferPassword ++ }, encryptedBuffer); ++ assert.strictEqual(decryptedBufferWithPassword.toString(), plaintext); ++ } ++ } ++ ++ encryptedBuffer = crypto.publicEncrypt(certPem, bufferToEncrypt); ++ ++ decryptedBuffer = crypto.privateDecrypt(keyPem, encryptedBuffer); ++ assert.strictEqual(decryptedBuffer.toString(), input); ++ ++ encryptedBuffer = crypto.publicEncrypt(keyPem, bufferToEncrypt); ++ ++ decryptedBuffer = crypto.privateDecrypt(keyPem, encryptedBuffer); ++ assert.strictEqual(decryptedBuffer.toString(), input); ++ ++ encryptedBuffer = crypto.privateEncrypt(keyPem, bufferToEncrypt); ++ ++ decryptedBuffer = crypto.publicDecrypt(keyPem, encryptedBuffer); ++ assert.strictEqual(decryptedBuffer.toString(), input); ++ ++ assert.throws(() => { ++ crypto.privateDecrypt({ ++ key: rsaKeyPemEncrypted, ++ passphrase: 'wrong' ++ }, bufferToEncrypt); ++ }, decryptError); ++ ++ assert.throws(() => { ++ crypto.publicEncrypt({ ++ key: rsaKeyPemEncrypted, ++ passphrase: 'wrong' ++ }, encryptedBuffer); ++ }, decryptError); ++ ++ encryptedBuffer = crypto.privateEncrypt({ ++ key: rsaKeyPemEncrypted, ++ passphrase: Buffer.from('password') ++ }, bufferToEncrypt); ++ ++ assert.throws(() => { ++ crypto.publicDecrypt({ ++ key: rsaKeyPemEncrypted, ++ passphrase: Buffer.from('wrong') ++ }, encryptedBuffer); ++ }, decryptError); ++} ++ ++function test_rsa(padding, encryptOaepHash, decryptOaepHash) { ++ const size = (padding === 'RSA_NO_PADDING') ? rsaKeySize / 8 : 32; ++ const input = Buffer.allocUnsafe(size); ++ for (let i = 0; i < input.length; i++) ++ input[i] = (i * 7 + 11) & 0xff; ++ const bufferToEncrypt = Buffer.from(input); ++ ++ padding = constants[padding]; ++ ++ const encryptedBuffer = crypto.publicEncrypt({ ++ key: rsaPubPem, ++ padding: padding, ++ oaepHash: encryptOaepHash ++ }, bufferToEncrypt); ++ ++ let decryptedBuffer = crypto.privateDecrypt({ ++ key: rsaKeyPem, ++ padding: padding, ++ oaepHash: decryptOaepHash ++ }, encryptedBuffer); ++ assert.deepStrictEqual(decryptedBuffer, input); ++ ++ decryptedBuffer = crypto.privateDecrypt({ ++ key: rsaPkcs8KeyPem, ++ padding: padding, ++ oaepHash: decryptOaepHash ++ }, encryptedBuffer); ++ assert.deepStrictEqual(decryptedBuffer, input); ++} ++ ++test_rsa('RSA_NO_PADDING'); ++test_rsa('RSA_PKCS1_PADDING'); ++test_rsa('RSA_PKCS1_OAEP_PADDING'); ++ ++// Test OAEP with different hash functions. ++test_rsa('RSA_PKCS1_OAEP_PADDING', undefined, 'sha1'); ++test_rsa('RSA_PKCS1_OAEP_PADDING', 'sha1', undefined); ++test_rsa('RSA_PKCS1_OAEP_PADDING', 'sha256', 'sha256'); ++test_rsa('RSA_PKCS1_OAEP_PADDING', 'sha512', 'sha512'); ++assert.throws(() => { ++ test_rsa('RSA_PKCS1_OAEP_PADDING', 'sha256', 'sha512'); ++}, { ++ code: 'ERR_OSSL_RSA_OAEP_DECODING_ERROR' ++}); ++ ++// The following RSA-OAEP test cases were created using the WebCrypto API to ++// ensure compatibility when using non-SHA1 hash functions. ++{ ++ const { decryptionTests } = ++ JSON.parse(fixtures.readSync('rsa-oaep-test-vectors.js', 'utf8')); ++ ++ for (const { ct, oaepHash, oaepLabel } of decryptionTests) { ++ const label = oaepLabel ? Buffer.from(oaepLabel, 'hex') : undefined; ++ const copiedLabel = oaepLabel ? getBufferCopy(label) : undefined; ++ ++ const decrypted = crypto.privateDecrypt({ ++ key: rsaPkcs8KeyPem, ++ oaepHash, ++ oaepLabel: oaepLabel ? label : undefined ++ }, Buffer.from(ct, 'hex')); ++ ++ assert.strictEqual(decrypted.toString('utf8'), 'Hello Node.js'); ++ } ++} ++ ++// Test invalid oaepHash and oaepLabel options. ++for (const fn of [crypto.publicEncrypt, crypto.privateDecrypt]) { ++ assert.throws(() => { ++ fn({ ++ key: rsaPubPem, ++ oaepHash: 'Hello world' ++ }, Buffer.alloc(10)); ++ }, { ++ code: 'ERR_OSSL_EVP_INVALID_DIGEST' ++ }); ++ ++ for (const oaepHash of [0, false, null, Symbol(), () => {}]) { ++ assert.throws(() => { ++ fn({ ++ key: rsaPubPem, ++ oaepHash ++ }, Buffer.alloc(10)); ++ }, { ++ code: 'ERR_INVALID_ARG_TYPE' ++ }); ++ } ++ ++ for (const oaepLabel of [0, false, null, Symbol(), () => {}, {}]) { ++ assert.throws(() => { ++ fn({ ++ key: rsaPubPem, ++ oaepLabel ++ }, Buffer.alloc(10)); ++ }, { ++ code: 'ERR_INVALID_ARG_TYPE' ++ }); ++ } ++} ++ ++// Test RSA key signing/verification ++let rsaSign = crypto.createSign('SHA1'); ++let rsaVerify = crypto.createVerify('SHA1'); ++assert.ok(rsaSign); ++assert.ok(rsaVerify); ++ ++const expectedSignature = fixtures.readKey( ++ 'rsa_public_sha1_signature_signedby_rsa_private_pkcs8.sha1', ++ 'hex' ++); ++ ++rsaSign.update(rsaPubPem); ++let rsaSignature = rsaSign.sign(rsaKeyPem, 'hex'); ++assert.strictEqual(rsaSignature, expectedSignature); ++ ++rsaVerify.update(rsaPubPem); ++assert.strictEqual(rsaVerify.verify(rsaPubPem, rsaSignature, 'hex'), true); ++ ++// Test RSA PKCS#8 key signing/verification ++rsaSign = crypto.createSign('SHA1'); ++rsaSign.update(rsaPubPem); ++rsaSignature = rsaSign.sign(rsaPkcs8KeyPem, 'hex'); ++assert.strictEqual(rsaSignature, expectedSignature); ++ ++rsaVerify = crypto.createVerify('SHA1'); ++rsaVerify.update(rsaPubPem); ++assert.strictEqual(rsaVerify.verify(rsaPubPem, rsaSignature, 'hex'), true); ++ ++// Test RSA key signing/verification with encrypted key ++rsaSign = crypto.createSign('SHA1'); ++rsaSign.update(rsaPubPem); ++const signOptions = { key: rsaKeyPemEncrypted, passphrase: 'password' }; ++rsaSignature = rsaSign.sign(signOptions, 'hex'); ++assert.strictEqual(rsaSignature, expectedSignature); ++ ++rsaVerify = crypto.createVerify('SHA1'); ++rsaVerify.update(rsaPubPem); ++assert.strictEqual(rsaVerify.verify(rsaPubPem, rsaSignature, 'hex'), true); ++ ++rsaSign = crypto.createSign('SHA1'); ++rsaSign.update(rsaPubPem); ++assert.throws(() => { ++ const signOptions = { key: rsaKeyPemEncrypted, passphrase: 'wrong' }; ++ rsaSign.sign(signOptions, 'hex'); ++}, decryptPrivateKeyError); ++ ++// ++// Test RSA signing and verification ++// ++{ ++ const privateKey = fixtures.readKey('rsa_private_b.pem'); ++ const publicKey = fixtures.readKey('rsa_public_b.pem'); ++ ++ const input = 'I AM THE WALRUS'; ++ ++ const signature = fixtures.readKey( ++ 'I_AM_THE_WALRUS_sha256_signature_signedby_rsa_private_b.sha256', ++ 'hex' ++ ); ++ ++ const sign = crypto.createSign('SHA256'); ++ sign.update(input); ++ ++ const output = sign.sign(privateKey, 'hex'); ++ assert.strictEqual(output, signature); ++ ++ const verify = crypto.createVerify('SHA256'); ++ verify.update(input); ++ ++ assert.strictEqual(verify.verify(publicKey, signature, 'hex'), true); ++ ++ // Test the legacy signature algorithm name. ++ const sign2 = crypto.createSign('RSA-SHA256'); ++ sign2.update(input); ++ ++ const output2 = sign2.sign(privateKey, 'hex'); ++ assert.strictEqual(output2, signature); ++ ++ const verify2 = crypto.createVerify('SHA256'); ++ verify2.update(input); ++ ++ assert.strictEqual(verify2.verify(publicKey, signature, 'hex'), true); ++} ++ ++ ++// ++// Test DSA signing and verification ++// ++{ ++ const input = 'I AM THE WALRUS'; ++ ++ // DSA signatures vary across runs so there is no static string to verify ++ // against. ++ const sign = crypto.createSign('SHA1'); ++ sign.update(input); ++ const signature = sign.sign(dsaKeyPem, 'hex'); ++ ++ const verify = crypto.createVerify('SHA1'); ++ verify.update(input); ++ ++ assert.strictEqual(verify.verify(dsaPubPem, signature, 'hex'), true); ++ ++ // Test the legacy 'DSS1' name. ++ const sign2 = crypto.createSign('DSS1'); ++ sign2.update(input); ++ const signature2 = sign2.sign(dsaKeyPem, 'hex'); ++ ++ const verify2 = crypto.createVerify('DSS1'); ++ verify2.update(input); ++ ++ assert.strictEqual(verify2.verify(dsaPubPem, signature2, 'hex'), true); ++} ++ ++ ++// ++// Test DSA signing and verification with PKCS#8 private key ++// ++{ ++ const input = 'I AM THE WALRUS'; ++ ++ // DSA signatures vary across runs so there is no static string to verify ++ // against. ++ const sign = crypto.createSign('SHA1'); ++ sign.update(input); ++ const signature = sign.sign(dsaPkcs8KeyPem, 'hex'); ++ ++ const verify = crypto.createVerify('SHA1'); ++ verify.update(input); ++ ++ assert.strictEqual(verify.verify(dsaPubPem, signature, 'hex'), true); ++} ++ ++ ++// ++// Test DSA signing and verification with encrypted key ++// ++const input = 'I AM THE WALRUS'; ++ ++{ ++ const sign = crypto.createSign('SHA1'); ++ sign.update(input); ++ assert.throws(() => { ++ sign.sign({ key: dsaKeyPemEncrypted, passphrase: 'wrong' }, 'hex'); ++ }, decryptPrivateKeyError); ++} ++ ++{ ++ // DSA signatures vary across runs so there is no static string to verify ++ // against. ++ const sign = crypto.createSign('SHA1'); ++ sign.update(input); ++ const signOptions = { key: dsaKeyPemEncrypted, passphrase: 'password' }; ++ const signature = sign.sign(signOptions, 'hex'); ++ ++ const verify = crypto.createVerify('SHA1'); ++ verify.update(input); ++ ++ assert.strictEqual(verify.verify(dsaPubPem, signature, 'hex'), true); ++} +diff --git a/test/parallel/test-crypto-rsa-dsa.js b/test/parallel/test-crypto-rsa-dsa.js +index 9b8c3f6..b45bfeb 100644 +--- a/test/parallel/test-crypto-rsa-dsa.js ++++ b/test/parallel/test-crypto-rsa-dsa.js +@@ -169,19 +169,37 @@ function test_rsa(padding, encryptOaepHash, decryptOaepHash) { + oaepHash: encryptOaepHash + }, bufferToEncrypt); + +- let decryptedBuffer = crypto.privateDecrypt({ +- key: rsaKeyPem, +- padding: padding, +- oaepHash: decryptOaepHash +- }, encryptedBuffer); +- assert.deepStrictEqual(decryptedBuffer, input); + +- decryptedBuffer = crypto.privateDecrypt({ +- key: rsaPkcs8KeyPem, +- padding: padding, +- oaepHash: decryptOaepHash +- }, encryptedBuffer); +- assert.deepStrictEqual(decryptedBuffer, input); ++ if (padding === constants.RSA_PKCS1_PADDING) { ++ assert.throws(() => { ++ crypto.privateDecrypt({ ++ key: rsaKeyPem, ++ padding: padding, ++ oaepHash: decryptOaepHash ++ }, encryptedBuffer); ++ }, { code: 'ERR_INVALID_ARG_VALUE' }); ++ assert.throws(() => { ++ crypto.privateDecrypt({ ++ key: rsaPkcs8KeyPem, ++ padding: padding, ++ oaepHash: decryptOaepHash ++ }, encryptedBuffer); ++ }, { code: 'ERR_INVALID_ARG_VALUE' }); ++ } else { ++ let decryptedBuffer = crypto.privateDecrypt({ ++ key: rsaKeyPem, ++ padding: padding, ++ oaepHash: decryptOaepHash ++ }, encryptedBuffer); ++ assert.deepStrictEqual(decryptedBuffer, input); ++ ++ decryptedBuffer = crypto.privateDecrypt({ ++ key: rsaPkcs8KeyPem, ++ padding: padding, ++ oaepHash: decryptOaepHash ++ }, encryptedBuffer); ++ assert.deepStrictEqual(decryptedBuffer, input); ++ } + } + + test_rsa('RSA_NO_PADDING'); diff --git a/CVE-2024-22019.patch b/CVE-2024-22019.patch new file mode 100644 index 0000000000000000000000000000000000000000..0e581d990a208b1468b0873284156704711c8d63 --- /dev/null +++ b/CVE-2024-22019.patch @@ -0,0 +1,565 @@ +From: Paolo Insogna +Date: Tue, 9 Jan 2024 18:10:04 +0100 +Subject: CVE-2024-22019: http: add maximum chunk extension size + +PR-URL: https://github.com/nodejs-private/node-private/pull/520 +Refs: https://github.com/nodejs-private/node-private/pull/518 +CVE-ID: CVE-2024-22019 +origin: backport, https://github.com/nodejs/node/commit/911cb33cdadab57a75f97186290ea8f3903a6171.patch +bug: https://nodejs.org/en/blog/vulnerability/february-2024-security-releases/#reading-unprocessed-http-request-with-unbounded-chunk-extension-allows-dos-attacks-cve-2024-22019---high +--- + deps/llhttp/include/llhttp.h | 4 + + deps/llhttp/src/api.c | 22 ++++ + deps/llhttp/src/llhttp.c | 122 +++++++++++++++++--- + doc/api/errors.md | 12 ++ + lib/_http_server.js | 25 ++++- + src/node_http_parser_impl.h | 25 ++++- + test/parallel/test-http-chunk-extensions-limit.js | 131 ++++++++++++++++++++++ + 7 files changed, 324 insertions(+), 17 deletions(-) + create mode 100644 test/parallel/test-http-chunk-extensions-limit.js + +diff --git a/deps/llhttp/include/llhttp.h b/deps/llhttp/include/llhttp.h +index fe3a927..d9cf6d3 100644 +--- a/deps/llhttp/include/llhttp.h ++++ b/deps/llhttp/include/llhttp.h +@@ -255,6 +255,10 @@ struct llhttp_settings_s { + */ + llhttp_cb on_headers_complete; + ++ /* Possible return values 0, -1, HPE_USER */ ++ llhttp_data_cb on_chunk_parameters; ++ ++ /* Possible return values 0, -1, HPE_USER */ + llhttp_data_cb on_body; + + /* Possible return values 0, -1, `HPE_PAUSED` */ +diff --git a/deps/llhttp/src/api.c b/deps/llhttp/src/api.c +index 6f72465..1b7ad0e 100644 +--- a/deps/llhttp/src/api.c ++++ b/deps/llhttp/src/api.c +@@ -15,6 +15,21 @@ + err = settings->NAME(__VA_ARGS__); \ + } while (0) + ++#define SPAN_CALLBACK_MAYBE(PARSER, NAME, START, LEN) \ ++ do { \ ++ const llhttp_settings_t* settings; \ ++ settings = (const llhttp_settings_t*) (PARSER)->settings; \ ++ if (settings == NULL || settings->NAME == NULL) { \ ++ err = 0; \ ++ break; \ ++ } \ ++ err = settings->NAME((PARSER), (START), (LEN)); \ ++ if (err == -1) { \ ++ err = HPE_USER; \ ++ llhttp_set_error_reason((PARSER), "Span callback error in " #NAME); \ ++ } \ ++ } while (0) ++ + void llhttp_init(llhttp_t* parser, llhttp_type_t type, + const llhttp_settings_t* settings) { + llhttp__internal_init(parser); +@@ -202,6 +217,13 @@ int llhttp__on_chunk_header(llhttp_t* s, const char* p, const char* endp) { + } + + ++int llhttp__on_chunk_parameters(llhttp_t* s, const char* p, const char* endp) { ++ int err; ++ SPAN_CALLBACK_MAYBE(s, on_chunk_parameters, p, endp - p); ++ return err; ++} ++ ++ + int llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) { + int err; + CALLBACK_MAYBE(s, on_chunk_complete, s); +diff --git a/deps/llhttp/src/llhttp.c b/deps/llhttp/src/llhttp.c +index e8f42ce..3fcea4b 100644 +--- a/deps/llhttp/src/llhttp.c ++++ b/deps/llhttp/src/llhttp.c +@@ -307,6 +307,8 @@ enum llparse_state_e { + s_n_llhttp__internal__n_invoke_is_equal_content_length, + s_n_llhttp__internal__n_chunk_size_almost_done, + s_n_llhttp__internal__n_chunk_parameters, ++ s_n_llhttp__internal__n_span_start_llhttp__on_chunk_parameters, ++ s_n_llhttp__internal__n_chunk_parameters_ows, + s_n_llhttp__internal__n_chunk_size_otherwise, + s_n_llhttp__internal__n_chunk_size, + s_n_llhttp__internal__n_chunk_size_digit, +@@ -482,6 +484,10 @@ int llhttp__on_body( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + ++int llhttp__on_chunk_parameters( ++ llhttp__internal_t* s, const unsigned char* p, ++ const unsigned char* endp); ++ + int llhttp__on_status( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); +@@ -1118,8 +1124,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_chunk_parameters; + } + case 2: { +- p++; +- goto s_n_llhttp__internal__n_chunk_size_almost_done; ++ goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_parameters; + } + default: { + goto s_n_llhttp__internal__n_error_10; +@@ -1128,6 +1133,34 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } ++ case s_n_llhttp__internal__n_span_start_llhttp__on_chunk_parameters: ++ s_n_llhttp__internal__n_span_start_llhttp__on_chunk_parameters: { ++ if (p == endp) { ++ return s_n_llhttp__internal__n_span_start_llhttp__on_chunk_parameters; ++ } ++ state->_span_pos0 = (void*) p; ++ state->_span_cb0 = llhttp__on_chunk_parameters; ++ goto s_n_llhttp__internal__n_chunk_parameters; ++ /* UNREACHABLE */; ++ abort(); ++ } ++ case s_n_llhttp__internal__n_chunk_parameters_ows: ++ s_n_llhttp__internal__n_chunk_parameters_ows: { ++ if (p == endp) { ++ return s_n_llhttp__internal__n_chunk_parameters_ows; ++ } ++ switch (*p) { ++ case ' ': { ++ p++; ++ goto s_n_llhttp__internal__n_chunk_parameters_ows; ++ } ++ default: { ++ goto s_n_llhttp__internal__n_span_start_llhttp__on_chunk_parameters; ++ } ++ } ++ /* UNREACHABLE */; ++ abort(); ++ } + case s_n_llhttp__internal__n_chunk_size_otherwise: + s_n_llhttp__internal__n_chunk_size_otherwise: { + if (p == endp) { +@@ -1138,13 +1171,9 @@ static llparse_state_t llhttp__internal__run( + p++; + goto s_n_llhttp__internal__n_chunk_size_almost_done; + } +- case ' ': { +- p++; +- goto s_n_llhttp__internal__n_chunk_parameters; +- } + case ';': { + p++; +- goto s_n_llhttp__internal__n_chunk_parameters; ++ goto s_n_llhttp__internal__n_chunk_parameters_ows; + } + default: { + goto s_n_llhttp__internal__n_error_11; +@@ -5449,6 +5478,24 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } ++ s_n_llhttp__internal__n_span_end_llhttp__on_chunk_parameters: { ++ const unsigned char* start; ++ int err; ++ ++ start = state->_span_pos0; ++ state->_span_pos0 = NULL; ++ err = llhttp__on_chunk_parameters(state, start, p); ++ if (err != 0) { ++ state->error = err; ++ state->error_pos = (const char*) (p + 1); ++ state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_chunk_size_almost_done; ++ return s_error; ++ } ++ p++; ++ goto s_n_llhttp__internal__n_chunk_size_almost_done; ++ /* UNREACHABLE */; ++ abort(); ++ } + s_n_llhttp__internal__n_error_10: { + state->error = 0x2; + state->reason = "Invalid character in chunk parameters"; +@@ -7414,6 +7461,8 @@ enum llparse_state_e { + s_n_llhttp__internal__n_invoke_is_equal_content_length, + s_n_llhttp__internal__n_chunk_size_almost_done, + s_n_llhttp__internal__n_chunk_parameters, ++ s_n_llhttp__internal__n_span_start_llhttp__on_chunk_parameters, ++ s_n_llhttp__internal__n_chunk_parameters_ows, + s_n_llhttp__internal__n_chunk_size_otherwise, + s_n_llhttp__internal__n_chunk_size, + s_n_llhttp__internal__n_chunk_size_digit, +@@ -7584,6 +7633,10 @@ int llhttp__on_body( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); + ++int llhttp__on_chunk_parameters( ++ llhttp__internal_t* s, const unsigned char* p, ++ const unsigned char* endp); ++ + int llhttp__on_status( + llhttp__internal_t* s, const unsigned char* p, + const unsigned char* endp); +@@ -8185,8 +8238,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_chunk_parameters; + } + case 2: { +- p++; +- goto s_n_llhttp__internal__n_chunk_size_almost_done; ++ goto s_n_llhttp__internal__n_span_end_llhttp__on_chunk_parameters; + } + default: { + goto s_n_llhttp__internal__n_error_6; +@@ -8195,6 +8247,34 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } ++ case s_n_llhttp__internal__n_span_start_llhttp__on_chunk_parameters: ++ s_n_llhttp__internal__n_span_start_llhttp__on_chunk_parameters: { ++ if (p == endp) { ++ return s_n_llhttp__internal__n_span_start_llhttp__on_chunk_parameters; ++ } ++ state->_span_pos0 = (void*) p; ++ state->_span_cb0 = llhttp__on_chunk_parameters; ++ goto s_n_llhttp__internal__n_chunk_parameters; ++ /* UNREACHABLE */; ++ abort(); ++ } ++ case s_n_llhttp__internal__n_chunk_parameters_ows: ++ s_n_llhttp__internal__n_chunk_parameters_ows: { ++ if (p == endp) { ++ return s_n_llhttp__internal__n_chunk_parameters_ows; ++ } ++ switch (*p) { ++ case ' ': { ++ p++; ++ goto s_n_llhttp__internal__n_chunk_parameters_ows; ++ } ++ default: { ++ goto s_n_llhttp__internal__n_span_start_llhttp__on_chunk_parameters; ++ } ++ } ++ /* UNREACHABLE */; ++ abort(); ++ } + case s_n_llhttp__internal__n_chunk_size_otherwise: + s_n_llhttp__internal__n_chunk_size_otherwise: { + if (p == endp) { +@@ -8205,13 +8285,9 @@ static llparse_state_t llhttp__internal__run( + p++; + goto s_n_llhttp__internal__n_chunk_size_almost_done; + } +- case ' ': { +- p++; +- goto s_n_llhttp__internal__n_chunk_parameters; +- } + case ';': { + p++; +- goto s_n_llhttp__internal__n_chunk_parameters; ++ goto s_n_llhttp__internal__n_chunk_parameters_ows; + } + default: { + goto s_n_llhttp__internal__n_error_7; +@@ -12312,6 +12388,24 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } ++ s_n_llhttp__internal__n_span_end_llhttp__on_chunk_parameters: { ++ const unsigned char* start; ++ int err; ++ ++ start = state->_span_pos0; ++ state->_span_pos0 = NULL; ++ err = llhttp__on_chunk_parameters(state, start, p); ++ if (err != 0) { ++ state->error = err; ++ state->error_pos = (const char*) (p + 1); ++ state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_chunk_size_almost_done; ++ return s_error; ++ } ++ p++; ++ goto s_n_llhttp__internal__n_chunk_size_almost_done; ++ /* UNREACHABLE */; ++ abort(); ++ } + s_n_llhttp__internal__n_error_6: { + state->error = 0x2; + state->reason = "Invalid character in chunk parameters"; +diff --git a/doc/api/errors.md b/doc/api/errors.md +index 4dbb51b..3c8a858 100644 +--- a/doc/api/errors.md ++++ b/doc/api/errors.md +@@ -2212,6 +2212,18 @@ malconfigured clients, if more than 8KB of HTTP header data is received then + HTTP parsing will abort without a request or response object being created, and + an `Error` with this code will be emitted. + ++ ++ ++### `HPE_CHUNK_EXTENSIONS_OVERFLOW` ++ ++ ++ ++Too much data was received for a chunk extensions. In order to protect against ++malicious or malconfigured clients, if more than 16 KiB of data is received ++then an `Error` with this code will be emitted. ++ + + ### `HPE_UNEXPECTED_CONTENT_LENGTH` + +diff --git a/lib/_http_server.js b/lib/_http_server.js +index 4d1f8e4..31ebae0 100644 +--- a/lib/_http_server.js ++++ b/lib/_http_server.js +@@ -591,6 +591,11 @@ const requestHeaderFieldsTooLargeResponse = Buffer.from( + `HTTP/1.1 431 ${STATUS_CODES[431]}${CRLF}` + + `Connection: close${CRLF}${CRLF}`, 'ascii' + ); ++const requestChunkExtensionsTooLargeResponse = Buffer.from( ++ `HTTP/1.1 413 ${STATUS_CODES[413]}\r\n` + ++ 'Connection: close\r\n\r\n', 'ascii', ++); ++ + function socketOnError(e) { + // Ignore further errors + this.removeListener('error', socketOnError); +@@ -598,8 +603,24 @@ function socketOnError(e) { + + if (!this.server.emit('clientError', e, this)) { + if (this.writable && this.bytesWritten === 0) { +- const response = e.code === 'HPE_HEADER_OVERFLOW' ? +- requestHeaderFieldsTooLargeResponse : badRequestResponse; ++ let response; ++ ++ switch (e.code) { ++ case 'HPE_HEADER_OVERFLOW': ++ response = requestHeaderFieldsTooLargeResponse; ++ break; ++ case 'HPE_CHUNK_EXTENSIONS_OVERFLOW': ++ response = requestChunkExtensionsTooLargeResponse; ++ break; ++/* case 'ERR_HTTP_REQUEST_TIMEOUT': ++ response = requestTimeoutResponse; ++ break; ++*/ ++ default: ++ response = badRequestResponse; ++ break; ++ } ++ + this.write(response); + } + this.destroy(e); +diff --git a/src/node_http_parser_impl.h b/src/node_http_parser_impl.h +index 77d09a9..891a108 100644 +--- a/src/node_http_parser_impl.h ++++ b/src/node_http_parser_impl.h +@@ -84,6 +84,8 @@ const uint32_t kOnExecute = 4; + const uint32_t kOnTimeout = 5; + // Any more fields than this will be flushed into JS + const size_t kMaxHeaderFieldsCount = 32; ++// Maximum size of chunk extensions ++const size_t kMaxChunkExtensionsSize = 16384; + + inline bool IsOWS(char c) { + return c == ' ' || c == '\t'; +@@ -187,6 +189,9 @@ class Parser : public AsyncWrap, public StreamListener { + + int on_message_begin() { + num_fields_ = num_values_ = 0; ++#ifdef NODE_EXPERIMENTAL_HTTP ++ chunk_extensions_nread_ = 0; ++#endif + url_.Reset(); + status_message_.Reset(); + header_parsing_start_time_ = uv_hrtime(); +@@ -432,9 +437,22 @@ class Parser : public AsyncWrap, public StreamListener { + } + + #ifdef NODE_EXPERIMENTAL_HTTP +- // Reset nread for the next chunk ++ int on_chunk_extension(const char* at, size_t length) { ++ chunk_extensions_nread_ += length; ++ ++ if (chunk_extensions_nread_ > kMaxChunkExtensionsSize) { ++ llhttp_set_error_reason(&parser_, ++ "HPE_CHUNK_EXTENSIONS_OVERFLOW:Chunk extensions overflow"); ++ return HPE_USER; ++ } ++ ++ return 0; ++ } ++ ++ // Reset nread for the next chunk and also reset the extensions counter + int on_chunk_header() { + header_nread_ = 0; ++ chunk_extensions_nread_ = 0; + return 0; + } + +@@ -857,6 +875,7 @@ class Parser : public AsyncWrap, public StreamListener { + llhttp_init(&parser_, type, &settings); + llhttp_set_lenient(&parser_, lenient); + header_nread_ = 0; ++ chunk_extensions_nread_ = 0; + #else /* !NODE_EXPERIMENTAL_HTTP */ + http_parser_init(&parser_, type); + parser_.lenient_http_headers = lenient; +@@ -916,6 +935,7 @@ class Parser : public AsyncWrap, public StreamListener { + unsigned int execute_depth_ = 0; + bool pending_pause_ = false; + uint64_t header_nread_ = 0; ++ uint64_t chunk_extensions_nread_ = 0; + #endif /* NODE_EXPERIMENTAL_HTTP */ + uint64_t headers_timeout_; + uint64_t header_parsing_start_time_ = 0; +@@ -948,6 +968,9 @@ const parser_settings_t Parser::settings = { + Proxy::Raw, + Proxy::Raw, + Proxy::Raw, ++#ifdef NODE_EXPERIMENTAL_HTTP ++ Proxy::Raw, ++#endif + Proxy::Raw, + Proxy::Raw, + #ifdef NODE_EXPERIMENTAL_HTTP +diff --git a/test/parallel/test-http-chunk-extensions-limit.js b/test/parallel/test-http-chunk-extensions-limit.js +new file mode 100644 +index 0000000..6868b3d +--- /dev/null ++++ b/test/parallel/test-http-chunk-extensions-limit.js +@@ -0,0 +1,131 @@ ++'use strict'; ++ ++const common = require('../common'); ++const http = require('http'); ++const net = require('net'); ++const assert = require('assert'); ++ ++// Verify that chunk extensions are limited in size when sent all together. ++{ ++ const server = http.createServer((req, res) => { ++ req.on('end', () => { ++ res.writeHead(200, { 'Content-Type': 'text/plain' }); ++ res.end('bye'); ++ }); ++ ++ req.resume(); ++ }); ++ ++ server.listen(0, () => { ++ const sock = net.connect(server.address().port); ++ let data = ''; ++ ++ sock.on('data', (chunk) => data += chunk.toString('utf-8')); ++ ++ sock.on('end', common.mustCall(function() { ++ assert.strictEqual(data, 'HTTP/1.1 413 Payload Too Large\r\nConnection: close\r\n\r\n'); ++ server.close(); ++ })); ++ ++ sock.end('' + ++ 'GET / HTTP/1.1\r\n' + ++ 'Host: localhost:8080\r\n' + ++ 'Transfer-Encoding: chunked\r\n\r\n' + ++ '2;' + 'A'.repeat(20000) + '=bar\r\nAA\r\n' + ++ '0\r\n\r\n' ++ ); ++ }); ++} ++ ++// Verify that chunk extensions are limited in size when sent in intervals. ++{ ++ const server = http.createServer((req, res) => { ++ req.on('end', () => { ++ res.writeHead(200, { 'Content-Type': 'text/plain' }); ++ res.end('bye'); ++ }); ++ ++ req.resume(); ++ }); ++ ++ server.listen(0, () => { ++ const sock = net.connect(server.address().port); ++ let remaining = 20000; ++ let data = ''; ++ ++ const interval = setInterval( ++ () => { ++ if (remaining > 0) { ++ sock.write('A'.repeat(1000)); ++ } else { ++ sock.write('=bar\r\nAA\r\n0\r\n\r\n'); ++ clearInterval(interval); ++ } ++ ++ remaining -= 1000; ++ }, ++ common.platformTimeout(20), ++ ).unref(); ++ ++ sock.on('data', (chunk) => data += chunk.toString('utf-8')); ++ ++ sock.on('end', common.mustCall(function() { ++ assert.strictEqual(data, 'HTTP/1.1 413 Payload Too Large\r\nConnection: close\r\n\r\n'); ++ server.close(); ++ })); ++ ++ sock.write('' + ++ 'GET / HTTP/1.1\r\n' + ++ 'Host: localhost:8080\r\n' + ++ 'Transfer-Encoding: chunked\r\n\r\n' + ++ '2;' ++ ); ++ }); ++} ++ ++// Verify the chunk extensions is correctly reset after a chunk ++{ ++ const server = http.createServer((req, res) => { ++ req.on('end', () => { ++ res.writeHead(200, { 'content-type': 'text/plain', 'connection': 'close', 'date': 'now' }); ++ res.end('bye'); ++ }); ++ ++ req.resume(); ++ }); ++ ++ server.listen(0, () => { ++ const sock = net.connect(server.address().port); ++ let data = ''; ++ ++ sock.on('data', (chunk) => data += chunk.toString('utf-8')); ++ ++ sock.on('end', common.mustCall(function() { ++ assert.strictEqual( ++ data, ++ 'HTTP/1.1 200 OK\r\n' + ++ 'content-type: text/plain\r\n' + ++ 'connection: close\r\n' + ++ 'date: now\r\n' + ++ 'Transfer-Encoding: chunked\r\n' + ++ '\r\n' + ++ '3\r\n' + ++ 'bye\r\n' + ++ '0\r\n' + ++ '\r\n', ++ ); ++ ++ server.close(); ++ })); ++ ++ sock.end('' + ++ 'GET / HTTP/1.1\r\n' + ++ 'Host: localhost:8080\r\n' + ++ 'Transfer-Encoding: chunked\r\n\r\n' + ++ '2;' + 'A'.repeat(10000) + '=bar\r\nAA\r\n' + ++ '2;' + 'A'.repeat(10000) + '=bar\r\nAA\r\n' + ++ '2;' + 'A'.repeat(10000) + '=bar\r\nAA\r\n' + ++ '0\r\n\r\n' ++ ); ++ }); ++} diff --git a/CVE-2024-22025.patch b/CVE-2024-22025.patch new file mode 100644 index 0000000000000000000000000000000000000000..fc8459758e58e551aeb3586146b4fac462464369 --- /dev/null +++ b/CVE-2024-22025.patch @@ -0,0 +1,154 @@ +From: Matteo Collina +Date: Tue, 6 Feb 2024 16:47:20 +0100 +Subject: CVE-2024-22025 zlib: pause stream if outgoing buffer is full + +A vulnerability in Node.js has been identified, allowing for a Denial +of Service (DoS) attack through resource exhaustion when using the +fetch() function to retrieve content from an untrusted URL. The +vulnerability stems from the fact that the fetch() function in Node.js +always decodes Brotli, making it possible for an attacker to cause +resource exhaustion when fetching content from an untrusted URL. An +attacker controlling the URL passed into fetch() can exploit this +vulnerability to exhaust memory, potentially leading to process +termination, depending on the system configuration + +Signed-off-by: Matteo Collina +PR-URL: nodejs-private/node-private#540 +Reviewed-By: Robert Nagy +bug: https://nodejs.org/en/blog/release/v18.19.1 +bug-hakerone: https://hackerone.com/reports/2284065 +origin: backport, https://github.com/nodejs/node/commit/9052ef43dc2d1b0db340591a9bc9e45a25c01d90.patch +CVE-ID: CVE-2024-22025 +--- + lib/zlib.js | 33 +++++++++++++++++++++++++-------- + test/parallel/test-zlib-brotli-16GB.js | 22 ++++++++++++++++++++++ + test/parallel/test-zlib-params.js | 26 ++++++++++++++++---------- + 3 files changed, 63 insertions(+), 18 deletions(-) + create mode 100644 test/parallel/test-zlib-brotli-16GB.js + +diff --git a/lib/zlib.js b/lib/zlib.js +index a3641d6..1900530 100644 +--- a/lib/zlib.js ++++ b/lib/zlib.js +@@ -532,10 +532,11 @@ function processCallback() { + self.bytesWritten += inDelta; + + const have = handle.availOutBefore - availOutAfter; ++ let streamBufferIsFull = false; + if (have > 0) { + const out = self._outBuffer.slice(self._outOffset, self._outOffset + have); + self._outOffset += have; +- self.push(out); ++ streamBufferIsFull = !self.push(out); + } else { + assert(have === 0, 'have should not go down'); + } +@@ -560,13 +561,29 @@ function processCallback() { + handle.inOff += inDelta; + handle.availInBefore = availInAfter; + +- this.write(handle.flushFlag, +- this.buffer, // in +- handle.inOff, // in_off +- handle.availInBefore, // in_len +- self._outBuffer, // out +- self._outOffset, // out_off +- self._chunkSize); // out_len ++ ++ if (!streamBufferIsFull) { ++ this.write(handle.flushFlag, ++ this.buffer, // in ++ handle.inOff, // in_off ++ handle.availInBefore, // in_len ++ self._outBuffer, // out ++ self._outOffset, // out_off ++ self._chunkSize); // out_len ++ } else { ++ const oldRead = self._read; ++ self._read = (n) => { ++ self._read = oldRead; ++ this.write(handle.flushFlag, ++ this.buffer, // in ++ handle.inOff, // in_off ++ handle.availInBefore, // in_len ++ self._outBuffer, // out ++ self._outOffset, // out_off ++ self._chunkSize); // out_len ++ self._read(n); ++ }; ++ } + return; + } + +diff --git a/test/parallel/test-zlib-brotli-16GB.js b/test/parallel/test-zlib-brotli-16GB.js +new file mode 100644 +index 0000000..68c29a4 +--- /dev/null ++++ b/test/parallel/test-zlib-brotli-16GB.js +@@ -0,0 +1,22 @@ ++'use strict'; ++ ++const common = require('../common'); ++const { createBrotliDecompress } = require('zlib'); ++const strictEqual = require('assert').strictEqual; ++ ++// This tiny HEX string is a 16GB file. ++// This test verifies that the stream actually stops. ++/* eslint-disable max-len */ ++const content = 'cfffff7ff82700e2b14020f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c32200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bff3f'; ++ ++const buf = Buffer.from(content, 'hex'); ++ ++const decoder = createBrotliDecompress(); ++decoder.end(buf); ++ ++// We need to wait to verify that the libuv thread pool had time ++// to process the data and the buffer is not empty. ++setTimeout(common.mustCall(() => { ++ // There is only one chunk in the buffer ++ strictEqual(decoder._readableState.buffer.length, 1); ++}), common.platformTimeout(500)); +diff --git a/test/parallel/test-zlib-params.js b/test/parallel/test-zlib-params.js +index 293ceec..d6589e4 100644 +--- a/test/parallel/test-zlib-params.js ++++ b/test/parallel/test-zlib-params.js +@@ -12,23 +12,29 @@ const deflater = zlib.createDeflate(opts); + const chunk1 = file.slice(0, chunkSize); + const chunk2 = file.slice(chunkSize); + const blkhdr = Buffer.from([0x00, 0x5a, 0x82, 0xa5, 0x7d]); +-const expected = Buffer.concat([blkhdr, chunk2]); +-let actual; ++const blkftr = Buffer.from('010000ffff7dac3072', 'hex'); ++const expected = Buffer.concat([blkhdr, chunk2, blkftr]); ++const bufs = []; ++ ++function read() { ++ let buf; ++ while ((buf = deflater.read()) !== null) { ++ bufs.push(buf); ++ } ++} + + deflater.write(chunk1, function() { + deflater.params(0, zlib.constants.Z_DEFAULT_STRATEGY, function() { + while (deflater.read()); +- deflater.end(chunk2, function() { +- const bufs = []; +- let buf; +- while (buf = deflater.read()) +- bufs.push(buf); +- actual = Buffer.concat(bufs); +- }); +- }); ++ ++ deflater.on('readable', read); ++ ++ deflater.end(chunk2); ++ }); + while (deflater.read()); + }); + + process.once('exit', function() { ++ const actual = Buffer.concat(bufs); + assert.deepStrictEqual(actual, expected); + }); diff --git a/CVE-2024-27982.patch b/CVE-2024-27982.patch new file mode 100644 index 0000000000000000000000000000000000000000..013838dae2468a8e73dbf74ef5d773a0b9a85737 --- /dev/null +++ b/CVE-2024-27982.patch @@ -0,0 +1,3031 @@ +From: Paolo Insogna +Date: Fri, 15 Mar 2024 11:35:51 +0100 +Subject: CVE-2024-27982 http: do not allow OBS fold in headers by default + +The team has identified a critical vulnerability in the http server of +the most recent version of Node, where malformed headers can lead to +HTTP request smuggling. Specifically, if a space is placed before a +content-length header, it is not interpreted correctly, enabling +attackers to smuggle in a second request within the body of the first. + +PR-URL: https://github.com/nodejs-private/node-private/pull/558 +Refs: https://github.com/nodejs-private/node-private/pull/556 +Reviewed-By: Matteo Collina +Reviewed-By: Rafael Gonzaga +CVE-ID: CVE-2024-27982 +bug: https://nodejs.org/en/blog/vulnerability/april-2024-security-releases/ +origin: backport, https://github.com/nodejs/node/commit/5d4d5848cf557fba6dc0bfdd020471ea607950ca.patch +--- + deps/llhttp/include/llhttp.h | 1 + + deps/llhttp/src/api.c | 26 +- + deps/llhttp/src/llhttp.c | 736 ++++++++++-------- + test/parallel/test-http-multi-line-headers.js | 3 +- + .../test-http-transfer-encoding-smuggling.js | 5 +- + 5 files changed, 424 insertions(+), 347 deletions(-) + +diff --git a/deps/llhttp/include/llhttp.h b/deps/llhttp/include/llhttp.h +index d9cf6d3..f765063 100644 +--- a/deps/llhttp/include/llhttp.h ++++ b/deps/llhttp/include/llhttp.h +@@ -239,6 +239,7 @@ struct llhttp_settings_s { + /* Possible return values 0, -1, `HPE_PAUSED` */ + llhttp_cb on_message_begin; + ++ /* Possible return values 0, -1, HPE_USER */ + llhttp_data_cb on_url; + llhttp_data_cb on_status; + llhttp_data_cb on_header_field; +diff --git a/deps/llhttp/src/api.c b/deps/llhttp/src/api.c +index 1b7ad0e..6a4c26d 100644 +--- a/deps/llhttp/src/api.c ++++ b/deps/llhttp/src/api.c +@@ -4,7 +4,7 @@ + + #include "llhttp.h" + +-#define CALLBACK_MAYBE(PARSER, NAME, ...) \ ++#define CALLBACK_MAYBE(PARSER, NAME) \ + do { \ + llhttp_settings_t* settings; \ + settings = (llhttp_settings_t*) (PARSER)->settings; \ +@@ -12,7 +12,7 @@ + err = 0; \ + break; \ + } \ +- err = settings->NAME(__VA_ARGS__); \ ++ err = settings->NAME((PARSER)); \ + } while (0) + + #define SPAN_CALLBACK_MAYBE(PARSER, NAME, START, LEN) \ +@@ -59,7 +59,7 @@ llhttp_errno_t llhttp_finish(llhttp_t* parser) { + + switch (parser->finish) { + case HTTP_FINISH_SAFE_WITH_CB: +- CALLBACK_MAYBE(parser, on_message_complete, parser); ++ CALLBACK_MAYBE(parser, on_message_complete); + if (err != HPE_OK) return err; + + /* FALLTHROUGH */ +@@ -156,63 +156,63 @@ void llhttp_set_lenient(llhttp_t* parser, int enabled) { + + int llhttp__on_message_begin(llhttp_t* s, const char* p, const char* endp) { + int err; +- CALLBACK_MAYBE(s, on_message_begin, s); ++ CALLBACK_MAYBE(s, on_message_begin); + return err; + } + + + int llhttp__on_url(llhttp_t* s, const char* p, const char* endp) { + int err; +- CALLBACK_MAYBE(s, on_url, s, p, endp - p); ++ SPAN_CALLBACK_MAYBE(s, on_url, p, endp - p); + return err; + } + + + int llhttp__on_status(llhttp_t* s, const char* p, const char* endp) { + int err; +- CALLBACK_MAYBE(s, on_status, s, p, endp - p); ++ SPAN_CALLBACK_MAYBE(s, on_status, p, endp - p); + return err; + } + + + int llhttp__on_header_field(llhttp_t* s, const char* p, const char* endp) { + int err; +- CALLBACK_MAYBE(s, on_header_field, s, p, endp - p); ++ SPAN_CALLBACK_MAYBE(s, on_header_field, p, endp - p); + return err; + } + + + int llhttp__on_header_value(llhttp_t* s, const char* p, const char* endp) { + int err; +- CALLBACK_MAYBE(s, on_header_value, s, p, endp - p); ++ SPAN_CALLBACK_MAYBE(s, on_header_value, p, endp - p); + return err; + } + + + int llhttp__on_headers_complete(llhttp_t* s, const char* p, const char* endp) { + int err; +- CALLBACK_MAYBE(s, on_headers_complete, s); ++ CALLBACK_MAYBE(s, on_headers_complete); + return err; + } + + + int llhttp__on_message_complete(llhttp_t* s, const char* p, const char* endp) { + int err; +- CALLBACK_MAYBE(s, on_message_complete, s); ++ CALLBACK_MAYBE(s, on_message_complete); + return err; + } + + + int llhttp__on_body(llhttp_t* s, const char* p, const char* endp) { + int err; +- CALLBACK_MAYBE(s, on_body, s, p, endp - p); ++ SPAN_CALLBACK_MAYBE(s, on_body, p, endp - p); + return err; + } + + + int llhttp__on_chunk_header(llhttp_t* s, const char* p, const char* endp) { + int err; +- CALLBACK_MAYBE(s, on_chunk_header, s); ++ CALLBACK_MAYBE(s, on_chunk_header); + return err; + } + +@@ -226,7 +226,7 @@ int llhttp__on_chunk_parameters(llhttp_t* s, const char* p, const char* endp) { + + int llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) { + int err; +- CALLBACK_MAYBE(s, on_chunk_complete, s); ++ CALLBACK_MAYBE(s, on_chunk_complete); + return err; + } + +diff --git a/deps/llhttp/src/llhttp.c b/deps/llhttp/src/llhttp.c +index 3fcea4b..dd45ef9 100644 +--- a/deps/llhttp/src/llhttp.c ++++ b/deps/llhttp/src/llhttp.c +@@ -327,7 +327,7 @@ enum llparse_state_e { + s_n_llhttp__internal__n_header_value_lws, + s_n_llhttp__internal__n_header_value_almost_done, + s_n_llhttp__internal__n_header_value_lenient, +- s_n_llhttp__internal__n_error_26, ++ s_n_llhttp__internal__n_error_27, + s_n_llhttp__internal__n_header_value_otherwise, + s_n_llhttp__internal__n_header_value_connection_token, + s_n_llhttp__internal__n_header_value_connection_ws, +@@ -335,12 +335,12 @@ enum llparse_state_e { + s_n_llhttp__internal__n_header_value_connection_2, + s_n_llhttp__internal__n_header_value_connection_3, + s_n_llhttp__internal__n_header_value_connection, +- s_n_llhttp__internal__n_error_28, + s_n_llhttp__internal__n_error_29, ++ s_n_llhttp__internal__n_error_30, + s_n_llhttp__internal__n_header_value_content_length_ws, + s_n_llhttp__internal__n_header_value_content_length, ++ s_n_llhttp__internal__n_error_32, + s_n_llhttp__internal__n_error_31, +- s_n_llhttp__internal__n_error_30, + s_n_llhttp__internal__n_header_value_te_token_ows, + s_n_llhttp__internal__n_header_value, + s_n_llhttp__internal__n_header_value_te_token, +@@ -775,7 +775,7 @@ int llhttp__internal__c_update_header_state_7( + return 0; + } + +-int llhttp__internal__c_test_flags_7( ++int llhttp__internal__c_test_flags_10( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { +@@ -816,7 +816,7 @@ int llhttp__internal__c_or_flags_15( + return 0; + } + +-int llhttp__internal__c_test_flags_8( ++int llhttp__internal__c_test_flags_11( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { +@@ -1569,11 +1569,11 @@ static llparse_state_t llhttp__internal__run( + switch (*p) { + case 9: { + p++; +- goto s_n_llhttp__internal__n_error_22; ++ goto s_n_llhttp__internal__n_invoke_test_flags_6; + } + case ' ': { + p++; +- goto s_n_llhttp__internal__n_error_22; ++ goto s_n_llhttp__internal__n_invoke_test_flags_6; + } + default: { + goto s_n_llhttp__internal__n_invoke_load_header_state; +@@ -1593,7 +1593,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_header_value_discard_lws; + } + default: { +- goto s_n_llhttp__internal__n_error_24; ++ goto s_n_llhttp__internal__n_invoke_test_flags_7; + } + } + /* UNREACHABLE */; +@@ -1606,10 +1606,10 @@ static llparse_state_t llhttp__internal__run( + } + switch (*p) { + case 9: { +- goto s_n_llhttp__internal__n_invoke_load_header_state_3; ++ goto s_n_llhttp__internal__n_invoke_test_flags_8; + } + case ' ': { +- goto s_n_llhttp__internal__n_invoke_load_header_state_3; ++ goto s_n_llhttp__internal__n_invoke_test_flags_8; + } + default: { + goto s_n_llhttp__internal__n_invoke_load_header_state_4; +@@ -1629,7 +1629,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_header_value_lws; + } + default: { +- goto s_n_llhttp__internal__n_error_25; ++ goto s_n_llhttp__internal__n_error_26; + } + } + /* UNREACHABLE */; +@@ -1655,8 +1655,8 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- case s_n_llhttp__internal__n_error_26: +- s_n_llhttp__internal__n_error_26: { ++ case s_n_llhttp__internal__n_error_27: ++ s_n_llhttp__internal__n_error_27: { + state->error = 0xa; + state->reason = "Invalid header value char"; + state->error_pos = (const char*) p; +@@ -1675,7 +1675,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_1; + } + default: { +- goto s_n_llhttp__internal__n_invoke_test_flags_6; ++ goto s_n_llhttp__internal__n_invoke_test_flags_9; + } + } + /* UNREACHABLE */; +@@ -1852,8 +1852,8 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- case s_n_llhttp__internal__n_error_28: +- s_n_llhttp__internal__n_error_28: { ++ case s_n_llhttp__internal__n_error_29: ++ s_n_llhttp__internal__n_error_29: { + state->error = 0xb; + state->reason = "Content-Length overflow"; + state->error_pos = (const char*) p; +@@ -1862,8 +1862,8 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- case s_n_llhttp__internal__n_error_29: +- s_n_llhttp__internal__n_error_29: { ++ case s_n_llhttp__internal__n_error_30: ++ s_n_llhttp__internal__n_error_30: { + state->error = 0xb; + state->reason = "Invalid character in Content-Length"; + state->error_pos = (const char*) p; +@@ -1958,8 +1958,8 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- case s_n_llhttp__internal__n_error_31: +- s_n_llhttp__internal__n_error_31: { ++ case s_n_llhttp__internal__n_error_32: ++ s_n_llhttp__internal__n_error_32: { + state->error = 0xf; + state->reason = "Invalid `Transfer-Encoding` header value"; + state->error_pos = (const char*) p; +@@ -1968,8 +1968,8 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- case s_n_llhttp__internal__n_error_30: +- s_n_llhttp__internal__n_error_30: { ++ case s_n_llhttp__internal__n_error_31: ++ s_n_llhttp__internal__n_error_31: { + state->error = 0xf; + state->reason = "Invalid `Transfer-Encoding` header value"; + state->error_pos = (const char*) p; +@@ -2197,7 +2197,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_field_2; + } + default: { +- goto s_n_llhttp__internal__n_error_32; ++ goto s_n_llhttp__internal__n_error_33; + } + } + /* UNREACHABLE */; +@@ -2577,7 +2577,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_url_to_http_09; + } + default: { +- goto s_n_llhttp__internal__n_error_33; ++ goto s_n_llhttp__internal__n_error_34; + } + } + /* UNREACHABLE */; +@@ -2602,7 +2602,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_url_skip_lf_to_http09_1; + } + default: { +- goto s_n_llhttp__internal__n_error_33; ++ goto s_n_llhttp__internal__n_error_34; + } + } + /* UNREACHABLE */; +@@ -2619,7 +2619,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_header_field_start; + } + default: { +- goto s_n_llhttp__internal__n_error_34; ++ goto s_n_llhttp__internal__n_error_35; + } + } + /* UNREACHABLE */; +@@ -2640,7 +2640,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_req_http_end_1; + } + default: { +- goto s_n_llhttp__internal__n_error_34; ++ goto s_n_llhttp__internal__n_error_35; + } + } + /* UNREACHABLE */; +@@ -2703,7 +2703,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_invoke_store_http_minor; + } + default: { +- goto s_n_llhttp__internal__n_error_35; ++ goto s_n_llhttp__internal__n_error_36; + } + } + /* UNREACHABLE */; +@@ -2720,7 +2720,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_req_http_minor; + } + default: { +- goto s_n_llhttp__internal__n_error_36; ++ goto s_n_llhttp__internal__n_error_37; + } + } + /* UNREACHABLE */; +@@ -2783,7 +2783,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_invoke_store_http_major; + } + default: { +- goto s_n_llhttp__internal__n_error_37; ++ goto s_n_llhttp__internal__n_error_38; + } + } + /* UNREACHABLE */; +@@ -2807,7 +2807,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_req_http_start_1; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_39; ++ goto s_n_llhttp__internal__n_error_40; + } + } + /* UNREACHABLE */; +@@ -2831,7 +2831,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_req_http_start_2; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_39; ++ goto s_n_llhttp__internal__n_error_40; + } + } + /* UNREACHABLE */; +@@ -2856,7 +2856,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_req_http_start_2; + } + default: { +- goto s_n_llhttp__internal__n_error_39; ++ goto s_n_llhttp__internal__n_error_40; + } + } + /* UNREACHABLE */; +@@ -2947,7 +2947,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_url_fragment; + } + default: { +- goto s_n_llhttp__internal__n_error_40; ++ goto s_n_llhttp__internal__n_error_41; + } + } + /* UNREACHABLE */; +@@ -3008,7 +3008,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_span_end_stub_query_3; + } + default: { +- goto s_n_llhttp__internal__n_error_41; ++ goto s_n_llhttp__internal__n_error_42; + } + } + /* UNREACHABLE */; +@@ -3046,7 +3046,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_url_query; + } + default: { +- goto s_n_llhttp__internal__n_error_42; ++ goto s_n_llhttp__internal__n_error_43; + } + } + /* UNREACHABLE */; +@@ -3171,10 +3171,10 @@ static llparse_state_t llhttp__internal__run( + } + case 8: { + p++; +- goto s_n_llhttp__internal__n_error_43; ++ goto s_n_llhttp__internal__n_error_44; + } + default: { +- goto s_n_llhttp__internal__n_error_44; ++ goto s_n_llhttp__internal__n_error_45; + } + } + /* UNREACHABLE */; +@@ -3233,7 +3233,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_url_server_with_at; + } + default: { +- goto s_n_llhttp__internal__n_error_45; ++ goto s_n_llhttp__internal__n_error_46; + } + } + /* UNREACHABLE */; +@@ -3250,7 +3250,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_url_server; + } + default: { +- goto s_n_llhttp__internal__n_error_47; ++ goto s_n_llhttp__internal__n_error_48; + } + } + /* UNREACHABLE */; +@@ -3268,7 +3268,7 @@ static llparse_state_t llhttp__internal__run( + } + case 10: { + p++; +- goto s_n_llhttp__internal__n_error_46; ++ goto s_n_llhttp__internal__n_error_47; + } + case 12: { + p++; +@@ -3276,18 +3276,18 @@ static llparse_state_t llhttp__internal__run( + } + case 13: { + p++; +- goto s_n_llhttp__internal__n_error_46; ++ goto s_n_llhttp__internal__n_error_47; + } + case ' ': { + p++; +- goto s_n_llhttp__internal__n_error_46; ++ goto s_n_llhttp__internal__n_error_47; + } + case '/': { + p++; + goto s_n_llhttp__internal__n_url_schema_delim_1; + } + default: { +- goto s_n_llhttp__internal__n_error_47; ++ goto s_n_llhttp__internal__n_error_48; + } + } + /* UNREACHABLE */; +@@ -3333,7 +3333,7 @@ static llparse_state_t llhttp__internal__run( + } + case 2: { + p++; +- goto s_n_llhttp__internal__n_error_46; ++ goto s_n_llhttp__internal__n_error_47; + } + case 3: { + goto s_n_llhttp__internal__n_span_end_stub_schema; +@@ -3343,7 +3343,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_url_schema; + } + default: { +- goto s_n_llhttp__internal__n_error_48; ++ goto s_n_llhttp__internal__n_error_49; + } + } + /* UNREACHABLE */; +@@ -3379,7 +3379,7 @@ static llparse_state_t llhttp__internal__run( + } + case 2: { + p++; +- goto s_n_llhttp__internal__n_error_46; ++ goto s_n_llhttp__internal__n_error_47; + } + case 3: { + goto s_n_llhttp__internal__n_span_start_stub_path_2; +@@ -3388,7 +3388,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_url_schema; + } + default: { +- goto s_n_llhttp__internal__n_error_49; ++ goto s_n_llhttp__internal__n_error_50; + } + } + /* UNREACHABLE */; +@@ -3486,7 +3486,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_req_spaces_before_url; + } + default: { +- goto s_n_llhttp__internal__n_error_50; ++ goto s_n_llhttp__internal__n_error_51; + } + } + /* UNREACHABLE */; +@@ -3511,7 +3511,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_1; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3536,7 +3536,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_2; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3561,7 +3561,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_4; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3586,7 +3586,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_6; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3604,7 +3604,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3625,7 +3625,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_7; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3646,7 +3646,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_5; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3671,7 +3671,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_8; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3696,7 +3696,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_9; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3721,7 +3721,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_10; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3746,7 +3746,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_12; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3771,7 +3771,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_13; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3792,7 +3792,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_13; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3817,7 +3817,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_15; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3842,7 +3842,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_16; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3867,7 +3867,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_18; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3892,7 +3892,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_20; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3910,7 +3910,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3931,7 +3931,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_21; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3952,7 +3952,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_19; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -3977,7 +3977,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_22; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4006,7 +4006,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_22; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4031,7 +4031,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_23; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4056,7 +4056,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_24; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4081,7 +4081,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_26; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4106,7 +4106,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_27; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4131,7 +4131,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_31; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4156,7 +4156,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_32; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4177,7 +4177,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_32; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4194,7 +4194,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_30; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4216,7 +4216,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_29; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4241,7 +4241,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_34; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4263,7 +4263,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4292,7 +4292,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_33; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4317,7 +4317,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_37; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4342,7 +4342,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_38; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4363,7 +4363,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_38; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4380,7 +4380,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_36; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4405,7 +4405,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_40; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4430,7 +4430,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_41; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4455,7 +4455,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_42; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4480,7 +4480,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_42; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4505,7 +4505,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_43; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4530,7 +4530,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_46; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4555,7 +4555,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_48; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4580,7 +4580,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_49; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4601,7 +4601,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_49; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4626,7 +4626,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_50; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4651,7 +4651,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_50; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4668,7 +4668,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_45; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4741,7 +4741,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_44; + } + default: { +- goto s_n_llhttp__internal__n_error_59; ++ goto s_n_llhttp__internal__n_error_60; + } + } + /* UNREACHABLE */; +@@ -4758,7 +4758,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_header_field_start; + } + default: { +- goto s_n_llhttp__internal__n_error_52; ++ goto s_n_llhttp__internal__n_error_53; + } + } + /* UNREACHABLE */; +@@ -4833,7 +4833,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_res_status_start; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -4913,7 +4913,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_invoke_update_status_code; + } + default: { +- goto s_n_llhttp__internal__n_error_54; ++ goto s_n_llhttp__internal__n_error_55; + } + } + /* UNREACHABLE */; +@@ -4976,7 +4976,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_invoke_store_http_minor_1; + } + default: { +- goto s_n_llhttp__internal__n_error_55; ++ goto s_n_llhttp__internal__n_error_56; + } + } + /* UNREACHABLE */; +@@ -4993,7 +4993,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_res_http_minor; + } + default: { +- goto s_n_llhttp__internal__n_error_56; ++ goto s_n_llhttp__internal__n_error_57; + } + } + /* UNREACHABLE */; +@@ -5056,7 +5056,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_invoke_store_http_major_1; + } + default: { +- goto s_n_llhttp__internal__n_error_57; ++ goto s_n_llhttp__internal__n_error_58; + } + } + /* UNREACHABLE */; +@@ -5080,7 +5080,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_res; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_60; ++ goto s_n_llhttp__internal__n_error_61; + } + } + /* UNREACHABLE */; +@@ -5105,7 +5105,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_req_or_res_method_2; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_58; ++ goto s_n_llhttp__internal__n_error_59; + } + } + /* UNREACHABLE */; +@@ -5129,7 +5129,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_req_or_res_method_3; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_58; ++ goto s_n_llhttp__internal__n_error_59; + } + } + /* UNREACHABLE */; +@@ -5150,7 +5150,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_req_or_res_method_3; + } + default: { +- goto s_n_llhttp__internal__n_error_58; ++ goto s_n_llhttp__internal__n_error_59; + } + } + /* UNREACHABLE */; +@@ -5167,7 +5167,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_req_or_res_method_1; + } + default: { +- goto s_n_llhttp__internal__n_error_58; ++ goto s_n_llhttp__internal__n_error_59; + } + } + /* UNREACHABLE */; +@@ -5236,7 +5236,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_46: { ++ s_n_llhttp__internal__n_error_47: { + state->error = 0x7; + state->reason = "Invalid characters in url"; + state->error_pos = (const char*) p; +@@ -5751,6 +5751,16 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } ++ s_n_llhttp__internal__n_invoke_test_flags_6: { ++ switch (llhttp__internal__c_test_flags_2(state, p, endp)) { ++ case 1: ++ goto s_n_llhttp__internal__n_header_value_discard_ws; ++ default: ++ goto s_n_llhttp__internal__n_error_22; ++ } ++ /* UNREACHABLE */; ++ abort(); ++ } + s_n_llhttp__internal__n_error_23: { + state->error = 0xb; + state->reason = "Empty Content-Length"; +@@ -5871,6 +5881,16 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } ++ s_n_llhttp__internal__n_invoke_test_flags_7: { ++ switch (llhttp__internal__c_test_flags_2(state, p, endp)) { ++ case 1: ++ goto s_n_llhttp__internal__n_header_value_discard_lws; ++ default: ++ goto s_n_llhttp__internal__n_error_24; ++ } ++ /* UNREACHABLE */; ++ abort(); ++ } + s_n_llhttp__internal__n_invoke_update_header_state_1: { + switch (llhttp__internal__c_update_header_state_1(state, p, endp)) { + default: +@@ -5889,6 +5909,25 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } ++ s_n_llhttp__internal__n_error_25: { ++ state->error = 0xa; ++ state->reason = "Unexpected whitespace after header value"; ++ state->error_pos = (const char*) p; ++ state->_current = (void*) (intptr_t) s_error; ++ return s_error; ++ /* UNREACHABLE */; ++ abort(); ++ } ++ s_n_llhttp__internal__n_invoke_test_flags_8: { ++ switch (llhttp__internal__c_test_flags_2(state, p, endp)) { ++ case 1: ++ goto s_n_llhttp__internal__n_invoke_load_header_state_3; ++ default: ++ goto s_n_llhttp__internal__n_error_25; ++ } ++ /* UNREACHABLE */; ++ abort(); ++ } + s_n_llhttp__internal__n_invoke_update_header_state_2: { + switch (llhttp__internal__c_update_header_state(state, p, endp)) { + default: +@@ -5945,7 +5984,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_25: { ++ s_n_llhttp__internal__n_error_26: { + state->error = 0x3; + state->reason = "Missing expected LF after header value"; + state->error_pos = (const char*) p; +@@ -6017,14 +6056,14 @@ static llparse_state_t llhttp__internal__run( + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; +- state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_26; ++ state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_27; + return s_error; + } +- goto s_n_llhttp__internal__n_error_26; ++ goto s_n_llhttp__internal__n_error_27; + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_invoke_test_flags_6: { ++ s_n_llhttp__internal__n_invoke_test_flags_9: { + switch (llhttp__internal__c_test_flags_2(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_header_value_lenient; +@@ -6132,10 +6171,10 @@ static llparse_state_t llhttp__internal__run( + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; +- state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_28; ++ state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_29; + return s_error; + } +- goto s_n_llhttp__internal__n_error_28; ++ goto s_n_llhttp__internal__n_error_29; + /* UNREACHABLE */; + abort(); + } +@@ -6167,14 +6206,14 @@ static llparse_state_t llhttp__internal__run( + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; +- state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_29; ++ state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_30; + return s_error; + } +- goto s_n_llhttp__internal__n_error_29; ++ goto s_n_llhttp__internal__n_error_30; + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_27: { ++ s_n_llhttp__internal__n_error_28: { + state->error = 0x4; + state->reason = "Duplicate Content-Length"; + state->error_pos = (const char*) p; +@@ -6183,12 +6222,12 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_invoke_test_flags_7: { +- switch (llhttp__internal__c_test_flags_7(state, p, endp)) { ++ s_n_llhttp__internal__n_invoke_test_flags_10: { ++ switch (llhttp__internal__c_test_flags_10(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_header_value_content_length; + default: +- goto s_n_llhttp__internal__n_error_27; ++ goto s_n_llhttp__internal__n_error_28; + } + /* UNREACHABLE */; + abort(); +@@ -6203,11 +6242,11 @@ static llparse_state_t llhttp__internal__run( + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); +- state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_31; ++ state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_32; + return s_error; + } + p++; +- goto s_n_llhttp__internal__n_error_31; ++ goto s_n_llhttp__internal__n_error_32; + /* UNREACHABLE */; + abort(); + } +@@ -6229,15 +6268,15 @@ static llparse_state_t llhttp__internal__run( + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); +- state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_30; ++ state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_31; + return s_error; + } + p++; +- goto s_n_llhttp__internal__n_error_30; ++ goto s_n_llhttp__internal__n_error_31; + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_invoke_test_flags_9: { ++ s_n_llhttp__internal__n_invoke_test_flags_12: { + switch (llhttp__internal__c_test_flags_2(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_7; +@@ -6250,7 +6289,7 @@ static llparse_state_t llhttp__internal__run( + s_n_llhttp__internal__n_invoke_load_type_1: { + switch (llhttp__internal__c_load_type(state, p, endp)) { + case 1: +- goto s_n_llhttp__internal__n_invoke_test_flags_9; ++ goto s_n_llhttp__internal__n_invoke_test_flags_12; + default: + goto s_n_llhttp__internal__n_header_value_te_chunked; + } +@@ -6281,7 +6320,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_invoke_test_flags_10: { ++ s_n_llhttp__internal__n_invoke_test_flags_13: { + switch (llhttp__internal__c_test_flags_2(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_8; +@@ -6294,7 +6333,7 @@ static llparse_state_t llhttp__internal__run( + s_n_llhttp__internal__n_invoke_load_type_2: { + switch (llhttp__internal__c_load_type(state, p, endp)) { + case 1: +- goto s_n_llhttp__internal__n_invoke_test_flags_10; ++ goto s_n_llhttp__internal__n_invoke_test_flags_13; + default: + goto s_n_llhttp__internal__n_invoke_or_flags_17; + } +@@ -6309,8 +6348,8 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_invoke_test_flags_8: { +- switch (llhttp__internal__c_test_flags_8(state, p, endp)) { ++ s_n_llhttp__internal__n_invoke_test_flags_11: { ++ switch (llhttp__internal__c_test_flags_11(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_load_type_2; + default: +@@ -6332,9 +6371,9 @@ static llparse_state_t llhttp__internal__run( + case 1: + goto s_n_llhttp__internal__n_header_value_connection; + case 2: +- goto s_n_llhttp__internal__n_invoke_test_flags_7; ++ goto s_n_llhttp__internal__n_invoke_test_flags_10; + case 3: +- goto s_n_llhttp__internal__n_invoke_test_flags_8; ++ goto s_n_llhttp__internal__n_invoke_test_flags_11; + case 4: + goto s_n_llhttp__internal__n_invoke_or_flags_18; + default: +@@ -6379,7 +6418,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_32: { ++ s_n_llhttp__internal__n_error_33: { + state->error = 0xa; + state->reason = "Invalid header token"; + state->error_pos = (const char*) p; +@@ -6445,7 +6484,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_33: { ++ s_n_llhttp__internal__n_error_34: { + state->error = 0x7; + state->reason = "Expected CRLF"; + state->error_pos = (const char*) p; +@@ -6471,7 +6510,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_34: { ++ s_n_llhttp__internal__n_error_35: { + state->error = 0x9; + state->reason = "Expected CRLF after version"; + state->error_pos = (const char*) p; +@@ -6488,7 +6527,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_35: { ++ s_n_llhttp__internal__n_error_36: { + state->error = 0x9; + state->reason = "Invalid minor version"; + state->error_pos = (const char*) p; +@@ -6497,7 +6536,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_36: { ++ s_n_llhttp__internal__n_error_37: { + state->error = 0x9; + state->reason = "Expected dot"; + state->error_pos = (const char*) p; +@@ -6514,7 +6553,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_37: { ++ s_n_llhttp__internal__n_error_38: { + state->error = 0x9; + state->reason = "Invalid major version"; + state->error_pos = (const char*) p; +@@ -6523,7 +6562,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_39: { ++ s_n_llhttp__internal__n_error_40: { + state->error = 0x8; + state->reason = "Expected HTTP/"; + state->error_pos = (const char*) p; +@@ -6532,7 +6571,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_38: { ++ s_n_llhttp__internal__n_error_39: { + state->error = 0x8; + state->reason = "Expected SOURCE method for ICE/x.x request"; + state->error_pos = (const char*) p; +@@ -6544,7 +6583,7 @@ static llparse_state_t llhttp__internal__run( + s_n_llhttp__internal__n_invoke_is_equal_method_1: { + switch (llhttp__internal__c_is_equal_method_1(state, p, endp)) { + case 0: +- goto s_n_llhttp__internal__n_error_38; ++ goto s_n_llhttp__internal__n_error_39; + default: + goto s_n_llhttp__internal__n_req_http_major; + } +@@ -6619,7 +6658,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_40: { ++ s_n_llhttp__internal__n_error_41: { + state->error = 0x7; + state->reason = "Invalid char in url fragment start"; + state->error_pos = (const char*) p; +@@ -6679,7 +6718,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_41: { ++ s_n_llhttp__internal__n_error_42: { + state->error = 0x7; + state->reason = "Invalid char in url query"; + state->error_pos = (const char*) p; +@@ -6688,7 +6727,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_42: { ++ s_n_llhttp__internal__n_error_43: { + state->error = 0x7; + state->reason = "Invalid char in url path"; + state->error_pos = (const char*) p; +@@ -6799,7 +6838,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_43: { ++ s_n_llhttp__internal__n_error_44: { + state->error = 0x7; + state->reason = "Double @ in url"; + state->error_pos = (const char*) p; +@@ -6808,7 +6847,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_44: { ++ s_n_llhttp__internal__n_error_45: { + state->error = 0x7; + state->reason = "Unexpected char in url server"; + state->error_pos = (const char*) p; +@@ -6817,7 +6856,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_45: { ++ s_n_llhttp__internal__n_error_46: { + state->error = 0x7; + state->reason = "Unexpected char in url server"; + state->error_pos = (const char*) p; +@@ -6826,7 +6865,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_47: { ++ s_n_llhttp__internal__n_error_48: { + state->error = 0x7; + state->reason = "Unexpected char in url schema"; + state->error_pos = (const char*) p; +@@ -6835,7 +6874,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_48: { ++ s_n_llhttp__internal__n_error_49: { + state->error = 0x7; + state->reason = "Unexpected char in url schema"; + state->error_pos = (const char*) p; +@@ -6844,7 +6883,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_49: { ++ s_n_llhttp__internal__n_error_50: { + state->error = 0x7; + state->reason = "Unexpected start char in url"; + state->error_pos = (const char*) p; +@@ -6863,7 +6902,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_50: { ++ s_n_llhttp__internal__n_error_51: { + state->error = 0x6; + state->reason = "Expected space after method"; + state->error_pos = (const char*) p; +@@ -6880,7 +6919,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_59: { ++ s_n_llhttp__internal__n_error_60: { + state->error = 0x6; + state->reason = "Invalid method encountered"; + state->error_pos = (const char*) p; +@@ -6889,7 +6928,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_51: { ++ s_n_llhttp__internal__n_error_52: { + state->error = 0xd; + state->reason = "Response overflow"; + state->error_pos = (const char*) p; +@@ -6901,14 +6940,14 @@ static llparse_state_t llhttp__internal__run( + s_n_llhttp__internal__n_invoke_mul_add_status_code: { + switch (llhttp__internal__c_mul_add_status_code(state, p, endp, match)) { + case 1: +- goto s_n_llhttp__internal__n_error_51; ++ goto s_n_llhttp__internal__n_error_52; + default: + goto s_n_llhttp__internal__n_res_status_code; + } + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_52: { ++ s_n_llhttp__internal__n_error_53: { + state->error = 0x2; + state->reason = "Expected LF after CR"; + state->error_pos = (const char*) p; +@@ -6953,7 +6992,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_53: { ++ s_n_llhttp__internal__n_error_54: { + state->error = 0xd; + state->reason = "Invalid response status"; + state->error_pos = (const char*) p; +@@ -6970,7 +7009,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_54: { ++ s_n_llhttp__internal__n_error_55: { + state->error = 0x9; + state->reason = "Expected space after version"; + state->error_pos = (const char*) p; +@@ -6987,7 +7026,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_55: { ++ s_n_llhttp__internal__n_error_56: { + state->error = 0x9; + state->reason = "Invalid minor version"; + state->error_pos = (const char*) p; +@@ -6996,7 +7035,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_56: { ++ s_n_llhttp__internal__n_error_57: { + state->error = 0x9; + state->reason = "Expected dot"; + state->error_pos = (const char*) p; +@@ -7013,7 +7052,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_57: { ++ s_n_llhttp__internal__n_error_58: { + state->error = 0x9; + state->reason = "Invalid major version"; + state->error_pos = (const char*) p; +@@ -7022,7 +7061,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_60: { ++ s_n_llhttp__internal__n_error_61: { + state->error = 0x8; + state->reason = "Expected HTTP/"; + state->error_pos = (const char*) p; +@@ -7047,7 +7086,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_58: { ++ s_n_llhttp__internal__n_error_59: { + state->error = 0x8; + state->reason = "Invalid word encountered"; + state->error_pos = (const char*) p; +@@ -7481,7 +7520,7 @@ enum llparse_state_e { + s_n_llhttp__internal__n_header_value_lws, + s_n_llhttp__internal__n_header_value_almost_done, + s_n_llhttp__internal__n_header_value_lenient, +- s_n_llhttp__internal__n_error_21, ++ s_n_llhttp__internal__n_error_22, + s_n_llhttp__internal__n_header_value_otherwise, + s_n_llhttp__internal__n_header_value_connection_token, + s_n_llhttp__internal__n_header_value_connection_ws, +@@ -7489,12 +7528,12 @@ enum llparse_state_e { + s_n_llhttp__internal__n_header_value_connection_2, + s_n_llhttp__internal__n_header_value_connection_3, + s_n_llhttp__internal__n_header_value_connection, +- s_n_llhttp__internal__n_error_23, + s_n_llhttp__internal__n_error_24, ++ s_n_llhttp__internal__n_error_25, + s_n_llhttp__internal__n_header_value_content_length_ws, + s_n_llhttp__internal__n_header_value_content_length, ++ s_n_llhttp__internal__n_error_27, + s_n_llhttp__internal__n_error_26, +- s_n_llhttp__internal__n_error_25, + s_n_llhttp__internal__n_header_value_te_token_ows, + s_n_llhttp__internal__n_header_value, + s_n_llhttp__internal__n_header_value_te_token, +@@ -7924,7 +7963,7 @@ int llhttp__internal__c_update_header_state_7( + return 0; + } + +-int llhttp__internal__c_test_flags_7( ++int llhttp__internal__c_test_flags_10( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { +@@ -7965,7 +8004,7 @@ int llhttp__internal__c_or_flags_15( + return 0; + } + +-int llhttp__internal__c_test_flags_8( ++int llhttp__internal__c_test_flags_11( + llhttp__internal_t* state, + const unsigned char* p, + const unsigned char* endp) { +@@ -8676,11 +8715,11 @@ static llparse_state_t llhttp__internal__run( + switch (*p) { + case 9: { + p++; +- goto s_n_llhttp__internal__n_error_17; ++ goto s_n_llhttp__internal__n_invoke_test_flags_6; + } + case ' ': { + p++; +- goto s_n_llhttp__internal__n_error_17; ++ goto s_n_llhttp__internal__n_invoke_test_flags_6; + } + default: { + goto s_n_llhttp__internal__n_invoke_load_header_state; +@@ -8700,7 +8739,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_header_value_discard_lws; + } + default: { +- goto s_n_llhttp__internal__n_error_19; ++ goto s_n_llhttp__internal__n_invoke_test_flags_7; + } + } + /* UNREACHABLE */; +@@ -8713,10 +8752,10 @@ static llparse_state_t llhttp__internal__run( + } + switch (*p) { + case 9: { +- goto s_n_llhttp__internal__n_invoke_load_header_state_3; ++ goto s_n_llhttp__internal__n_invoke_test_flags_8; + } + case ' ': { +- goto s_n_llhttp__internal__n_invoke_load_header_state_3; ++ goto s_n_llhttp__internal__n_invoke_test_flags_8; + } + default: { + goto s_n_llhttp__internal__n_invoke_load_header_state_4; +@@ -8736,7 +8775,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_header_value_lws; + } + default: { +- goto s_n_llhttp__internal__n_error_20; ++ goto s_n_llhttp__internal__n_error_21; + } + } + /* UNREACHABLE */; +@@ -8762,8 +8801,8 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- case s_n_llhttp__internal__n_error_21: +- s_n_llhttp__internal__n_error_21: { ++ case s_n_llhttp__internal__n_error_22: ++ s_n_llhttp__internal__n_error_22: { + state->error = 0xa; + state->reason = "Invalid header value char"; + state->error_pos = (const char*) p; +@@ -8782,7 +8821,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_1; + } + default: { +- goto s_n_llhttp__internal__n_invoke_test_flags_6; ++ goto s_n_llhttp__internal__n_invoke_test_flags_9; + } + } + /* UNREACHABLE */; +@@ -8959,8 +8998,8 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- case s_n_llhttp__internal__n_error_23: +- s_n_llhttp__internal__n_error_23: { ++ case s_n_llhttp__internal__n_error_24: ++ s_n_llhttp__internal__n_error_24: { + state->error = 0xb; + state->reason = "Content-Length overflow"; + state->error_pos = (const char*) p; +@@ -8969,8 +9008,8 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- case s_n_llhttp__internal__n_error_24: +- s_n_llhttp__internal__n_error_24: { ++ case s_n_llhttp__internal__n_error_25: ++ s_n_llhttp__internal__n_error_25: { + state->error = 0xb; + state->reason = "Invalid character in Content-Length"; + state->error_pos = (const char*) p; +@@ -9065,8 +9104,8 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- case s_n_llhttp__internal__n_error_26: +- s_n_llhttp__internal__n_error_26: { ++ case s_n_llhttp__internal__n_error_27: ++ s_n_llhttp__internal__n_error_27: { + state->error = 0xf; + state->reason = "Invalid `Transfer-Encoding` header value"; + state->error_pos = (const char*) p; +@@ -9075,8 +9114,8 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- case s_n_llhttp__internal__n_error_25: +- s_n_llhttp__internal__n_error_25: { ++ case s_n_llhttp__internal__n_error_26: ++ s_n_llhttp__internal__n_error_26: { + state->error = 0xf; + state->reason = "Invalid `Transfer-Encoding` header value"; + state->error_pos = (const char*) p; +@@ -9304,7 +9343,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_field_2; + } + default: { +- goto s_n_llhttp__internal__n_error_27; ++ goto s_n_llhttp__internal__n_error_28; + } + } + /* UNREACHABLE */; +@@ -9658,7 +9697,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_url_skip_lf_to_http09; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_28; ++ goto s_n_llhttp__internal__n_error_29; + } + } + /* UNREACHABLE */; +@@ -9675,7 +9714,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_header_field_start; + } + default: { +- goto s_n_llhttp__internal__n_error_29; ++ goto s_n_llhttp__internal__n_error_30; + } + } + /* UNREACHABLE */; +@@ -9696,7 +9735,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_req_http_end_1; + } + default: { +- goto s_n_llhttp__internal__n_error_29; ++ goto s_n_llhttp__internal__n_error_30; + } + } + /* UNREACHABLE */; +@@ -9759,7 +9798,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_invoke_store_http_minor; + } + default: { +- goto s_n_llhttp__internal__n_error_30; ++ goto s_n_llhttp__internal__n_error_31; + } + } + /* UNREACHABLE */; +@@ -9776,7 +9815,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_req_http_minor; + } + default: { +- goto s_n_llhttp__internal__n_error_31; ++ goto s_n_llhttp__internal__n_error_32; + } + } + /* UNREACHABLE */; +@@ -9839,7 +9878,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_invoke_store_http_major; + } + default: { +- goto s_n_llhttp__internal__n_error_32; ++ goto s_n_llhttp__internal__n_error_33; + } + } + /* UNREACHABLE */; +@@ -9863,7 +9902,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_req_http_start_1; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_34; ++ goto s_n_llhttp__internal__n_error_35; + } + } + /* UNREACHABLE */; +@@ -9887,7 +9926,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_req_http_start_2; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_34; ++ goto s_n_llhttp__internal__n_error_35; + } + } + /* UNREACHABLE */; +@@ -9912,7 +9951,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_req_http_start_2; + } + default: { +- goto s_n_llhttp__internal__n_error_34; ++ goto s_n_llhttp__internal__n_error_35; + } + } + /* UNREACHABLE */; +@@ -9966,7 +10005,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_span_end_llhttp__on_url_8; + } + default: { +- goto s_n_llhttp__internal__n_error_35; ++ goto s_n_llhttp__internal__n_error_36; + } + } + /* UNREACHABLE */; +@@ -10023,7 +10062,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_span_end_stub_query_3; + } + default: { +- goto s_n_llhttp__internal__n_error_36; ++ goto s_n_llhttp__internal__n_error_37; + } + } + /* UNREACHABLE */; +@@ -10053,7 +10092,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_url_query; + } + default: { +- goto s_n_llhttp__internal__n_error_37; ++ goto s_n_llhttp__internal__n_error_38; + } + } + /* UNREACHABLE */; +@@ -10194,10 +10233,10 @@ static llparse_state_t llhttp__internal__run( + } + case 7: { + p++; +- goto s_n_llhttp__internal__n_error_38; ++ goto s_n_llhttp__internal__n_error_39; + } + default: { +- goto s_n_llhttp__internal__n_error_39; ++ goto s_n_llhttp__internal__n_error_40; + } + } + /* UNREACHABLE */; +@@ -10252,7 +10291,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_url_server_with_at; + } + default: { +- goto s_n_llhttp__internal__n_error_40; ++ goto s_n_llhttp__internal__n_error_41; + } + } + /* UNREACHABLE */; +@@ -10269,7 +10308,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_url_server; + } + default: { +- goto s_n_llhttp__internal__n_error_42; ++ goto s_n_llhttp__internal__n_error_43; + } + } + /* UNREACHABLE */; +@@ -10283,22 +10322,22 @@ static llparse_state_t llhttp__internal__run( + switch (*p) { + case 10: { + p++; +- goto s_n_llhttp__internal__n_error_41; ++ goto s_n_llhttp__internal__n_error_42; + } + case 13: { + p++; +- goto s_n_llhttp__internal__n_error_41; ++ goto s_n_llhttp__internal__n_error_42; + } + case ' ': { + p++; +- goto s_n_llhttp__internal__n_error_41; ++ goto s_n_llhttp__internal__n_error_42; + } + case '/': { + p++; + goto s_n_llhttp__internal__n_url_schema_delim_1; + } + default: { +- goto s_n_llhttp__internal__n_error_42; ++ goto s_n_llhttp__internal__n_error_43; + } + } + /* UNREACHABLE */; +@@ -10340,7 +10379,7 @@ static llparse_state_t llhttp__internal__run( + switch (lookup_table[(uint8_t) *p]) { + case 1: { + p++; +- goto s_n_llhttp__internal__n_error_41; ++ goto s_n_llhttp__internal__n_error_42; + } + case 2: { + goto s_n_llhttp__internal__n_span_end_stub_schema; +@@ -10350,7 +10389,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_url_schema; + } + default: { +- goto s_n_llhttp__internal__n_error_43; ++ goto s_n_llhttp__internal__n_error_44; + } + } + /* UNREACHABLE */; +@@ -10382,7 +10421,7 @@ static llparse_state_t llhttp__internal__run( + switch (lookup_table[(uint8_t) *p]) { + case 1: { + p++; +- goto s_n_llhttp__internal__n_error_41; ++ goto s_n_llhttp__internal__n_error_42; + } + case 2: { + goto s_n_llhttp__internal__n_span_start_stub_path_2; +@@ -10391,7 +10430,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_url_schema; + } + default: { +- goto s_n_llhttp__internal__n_error_44; ++ goto s_n_llhttp__internal__n_error_45; + } + } + /* UNREACHABLE */; +@@ -10447,7 +10486,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_req_spaces_before_url; + } + default: { +- goto s_n_llhttp__internal__n_error_45; ++ goto s_n_llhttp__internal__n_error_46; + } + } + /* UNREACHABLE */; +@@ -10472,7 +10511,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_1; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10497,7 +10536,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_2; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10522,7 +10561,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_4; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10547,7 +10586,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_6; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10565,7 +10604,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10586,7 +10625,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_7; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10607,7 +10646,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_5; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10632,7 +10671,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_8; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10657,7 +10696,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_9; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10682,7 +10721,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_10; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10707,7 +10746,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_12; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10732,7 +10771,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_13; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10753,7 +10792,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_13; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10778,7 +10817,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_15; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10803,7 +10842,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_16; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10828,7 +10867,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_18; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10853,7 +10892,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_20; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10871,7 +10910,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10892,7 +10931,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_21; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10913,7 +10952,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_19; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10938,7 +10977,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_22; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10967,7 +11006,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_22; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -10992,7 +11031,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_23; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11017,7 +11056,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_24; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11042,7 +11081,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_26; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11067,7 +11106,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_27; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11092,7 +11131,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_31; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11117,7 +11156,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_32; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11138,7 +11177,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_32; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11155,7 +11194,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_30; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11177,7 +11216,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_29; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11202,7 +11241,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_34; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11224,7 +11263,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_invoke_store_method_1; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11253,7 +11292,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_33; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11278,7 +11317,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_37; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11303,7 +11342,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_38; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11324,7 +11363,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_38; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11341,7 +11380,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_36; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11366,7 +11405,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_40; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11391,7 +11430,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_41; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11416,7 +11455,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_42; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11441,7 +11480,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_42; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11466,7 +11505,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_43; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11491,7 +11530,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_46; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11516,7 +11555,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_48; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11541,7 +11580,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_49; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11562,7 +11601,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_49; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11587,7 +11626,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_req_50; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11612,7 +11651,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_50; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11629,7 +11668,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_45; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11702,7 +11741,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_start_req_44; + } + default: { +- goto s_n_llhttp__internal__n_error_53; ++ goto s_n_llhttp__internal__n_error_54; + } + } + /* UNREACHABLE */; +@@ -11787,7 +11826,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_res_status_start; + } + default: { +- goto s_n_llhttp__internal__n_error_47; ++ goto s_n_llhttp__internal__n_error_48; + } + } + /* UNREACHABLE */; +@@ -11867,7 +11906,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_invoke_update_status_code; + } + default: { +- goto s_n_llhttp__internal__n_error_48; ++ goto s_n_llhttp__internal__n_error_49; + } + } + /* UNREACHABLE */; +@@ -11930,7 +11969,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_invoke_store_http_minor_1; + } + default: { +- goto s_n_llhttp__internal__n_error_49; ++ goto s_n_llhttp__internal__n_error_50; + } + } + /* UNREACHABLE */; +@@ -11947,7 +11986,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_res_http_minor; + } + default: { +- goto s_n_llhttp__internal__n_error_50; ++ goto s_n_llhttp__internal__n_error_51; + } + } + /* UNREACHABLE */; +@@ -12010,7 +12049,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_invoke_store_http_major_1; + } + default: { +- goto s_n_llhttp__internal__n_error_51; ++ goto s_n_llhttp__internal__n_error_52; + } + } + /* UNREACHABLE */; +@@ -12034,7 +12073,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_start_res; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_54; ++ goto s_n_llhttp__internal__n_error_55; + } + } + /* UNREACHABLE */; +@@ -12059,7 +12098,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_req_or_res_method_2; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_52; ++ goto s_n_llhttp__internal__n_error_53; + } + } + /* UNREACHABLE */; +@@ -12083,7 +12122,7 @@ static llparse_state_t llhttp__internal__run( + return s_n_llhttp__internal__n_req_or_res_method_3; + } + case kMatchMismatch: { +- goto s_n_llhttp__internal__n_error_52; ++ goto s_n_llhttp__internal__n_error_53; + } + } + /* UNREACHABLE */; +@@ -12104,7 +12143,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_req_or_res_method_3; + } + default: { +- goto s_n_llhttp__internal__n_error_52; ++ goto s_n_llhttp__internal__n_error_53; + } + } + /* UNREACHABLE */; +@@ -12121,7 +12160,7 @@ static llparse_state_t llhttp__internal__run( + goto s_n_llhttp__internal__n_req_or_res_method_1; + } + default: { +- goto s_n_llhttp__internal__n_error_52; ++ goto s_n_llhttp__internal__n_error_53; + } + } + /* UNREACHABLE */; +@@ -12181,7 +12220,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */ + abort(); + } +- s_n_llhttp__internal__n_error_41: { ++ s_n_llhttp__internal__n_error_42: { + state->error = 0x7; + state->reason = "Invalid characters in url"; + state->error_pos = (const char*) p; +@@ -12652,6 +12691,16 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } ++ s_n_llhttp__internal__n_invoke_test_flags_6: { ++ switch (llhttp__internal__c_test_flags_2(state, p, endp)) { ++ case 1: ++ goto s_n_llhttp__internal__n_header_value_discard_ws; ++ default: ++ goto s_n_llhttp__internal__n_error_17; ++ } ++ /* UNREACHABLE */; ++ abort(); ++ } + s_n_llhttp__internal__n_error_18: { + state->error = 0xb; + state->reason = "Empty Content-Length"; +@@ -12772,6 +12821,16 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } ++ s_n_llhttp__internal__n_invoke_test_flags_7: { ++ switch (llhttp__internal__c_test_flags_2(state, p, endp)) { ++ case 1: ++ goto s_n_llhttp__internal__n_header_value_discard_lws; ++ default: ++ goto s_n_llhttp__internal__n_error_19; ++ } ++ /* UNREACHABLE */; ++ abort(); ++ } + s_n_llhttp__internal__n_invoke_update_header_state_1: { + switch (llhttp__internal__c_update_header_state_1(state, p, endp)) { + default: +@@ -12790,6 +12849,25 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } ++ s_n_llhttp__internal__n_error_20: { ++ state->error = 0xa; ++ state->reason = "Unexpected whitespace after header value"; ++ state->error_pos = (const char*) p; ++ state->_current = (void*) (intptr_t) s_error; ++ return s_error; ++ /* UNREACHABLE */; ++ abort(); ++ } ++ s_n_llhttp__internal__n_invoke_test_flags_8: { ++ switch (llhttp__internal__c_test_flags_2(state, p, endp)) { ++ case 1: ++ goto s_n_llhttp__internal__n_invoke_load_header_state_3; ++ default: ++ goto s_n_llhttp__internal__n_error_20; ++ } ++ /* UNREACHABLE */; ++ abort(); ++ } + s_n_llhttp__internal__n_invoke_update_header_state_2: { + switch (llhttp__internal__c_update_header_state(state, p, endp)) { + default: +@@ -12846,7 +12924,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_20: { ++ s_n_llhttp__internal__n_error_21: { + state->error = 0x3; + state->reason = "Missing expected LF after header value"; + state->error_pos = (const char*) p; +@@ -12918,14 +12996,14 @@ static llparse_state_t llhttp__internal__run( + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; +- state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_21; ++ state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_22; + return s_error; + } +- goto s_n_llhttp__internal__n_error_21; ++ goto s_n_llhttp__internal__n_error_22; + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_invoke_test_flags_6: { ++ s_n_llhttp__internal__n_invoke_test_flags_9: { + switch (llhttp__internal__c_test_flags_2(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_header_value_lenient; +@@ -13033,10 +13111,10 @@ static llparse_state_t llhttp__internal__run( + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; +- state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_23; ++ state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_24; + return s_error; + } +- goto s_n_llhttp__internal__n_error_23; ++ goto s_n_llhttp__internal__n_error_24; + /* UNREACHABLE */; + abort(); + } +@@ -13068,14 +13146,14 @@ static llparse_state_t llhttp__internal__run( + if (err != 0) { + state->error = err; + state->error_pos = (const char*) p; +- state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_24; ++ state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_25; + return s_error; + } +- goto s_n_llhttp__internal__n_error_24; ++ goto s_n_llhttp__internal__n_error_25; + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_22: { ++ s_n_llhttp__internal__n_error_23: { + state->error = 0x4; + state->reason = "Duplicate Content-Length"; + state->error_pos = (const char*) p; +@@ -13084,12 +13162,12 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_invoke_test_flags_7: { +- switch (llhttp__internal__c_test_flags_7(state, p, endp)) { ++ s_n_llhttp__internal__n_invoke_test_flags_10: { ++ switch (llhttp__internal__c_test_flags_10(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_header_value_content_length; + default: +- goto s_n_llhttp__internal__n_error_22; ++ goto s_n_llhttp__internal__n_error_23; + } + /* UNREACHABLE */; + abort(); +@@ -13104,11 +13182,11 @@ static llparse_state_t llhttp__internal__run( + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); +- state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_26; ++ state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_27; + return s_error; + } + p++; +- goto s_n_llhttp__internal__n_error_26; ++ goto s_n_llhttp__internal__n_error_27; + /* UNREACHABLE */; + abort(); + } +@@ -13130,15 +13208,15 @@ static llparse_state_t llhttp__internal__run( + if (err != 0) { + state->error = err; + state->error_pos = (const char*) (p + 1); +- state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_25; ++ state->_current = (void*) (intptr_t) s_n_llhttp__internal__n_error_26; + return s_error; + } + p++; +- goto s_n_llhttp__internal__n_error_25; ++ goto s_n_llhttp__internal__n_error_26; + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_invoke_test_flags_9: { ++ s_n_llhttp__internal__n_invoke_test_flags_12: { + switch (llhttp__internal__c_test_flags_2(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_7; +@@ -13151,7 +13229,7 @@ static llparse_state_t llhttp__internal__run( + s_n_llhttp__internal__n_invoke_load_type_1: { + switch (llhttp__internal__c_load_type(state, p, endp)) { + case 1: +- goto s_n_llhttp__internal__n_invoke_test_flags_9; ++ goto s_n_llhttp__internal__n_invoke_test_flags_12; + default: + goto s_n_llhttp__internal__n_header_value_te_chunked; + } +@@ -13182,7 +13260,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_invoke_test_flags_10: { ++ s_n_llhttp__internal__n_invoke_test_flags_13: { + switch (llhttp__internal__c_test_flags_2(state, p, endp)) { + case 0: + goto s_n_llhttp__internal__n_span_end_llhttp__on_header_value_8; +@@ -13195,7 +13273,7 @@ static llparse_state_t llhttp__internal__run( + s_n_llhttp__internal__n_invoke_load_type_2: { + switch (llhttp__internal__c_load_type(state, p, endp)) { + case 1: +- goto s_n_llhttp__internal__n_invoke_test_flags_10; ++ goto s_n_llhttp__internal__n_invoke_test_flags_13; + default: + goto s_n_llhttp__internal__n_invoke_or_flags_17; + } +@@ -13210,8 +13288,8 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_invoke_test_flags_8: { +- switch (llhttp__internal__c_test_flags_8(state, p, endp)) { ++ s_n_llhttp__internal__n_invoke_test_flags_11: { ++ switch (llhttp__internal__c_test_flags_11(state, p, endp)) { + case 1: + goto s_n_llhttp__internal__n_invoke_load_type_2; + default: +@@ -13233,9 +13311,9 @@ static llparse_state_t llhttp__internal__run( + case 1: + goto s_n_llhttp__internal__n_header_value_connection; + case 2: +- goto s_n_llhttp__internal__n_invoke_test_flags_7; ++ goto s_n_llhttp__internal__n_invoke_test_flags_10; + case 3: +- goto s_n_llhttp__internal__n_invoke_test_flags_8; ++ goto s_n_llhttp__internal__n_invoke_test_flags_11; + case 4: + goto s_n_llhttp__internal__n_invoke_or_flags_18; + default: +@@ -13280,7 +13358,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_27: { ++ s_n_llhttp__internal__n_error_28: { + state->error = 0xa; + state->reason = "Invalid header token"; + state->error_pos = (const char*) p; +@@ -13346,7 +13424,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_28: { ++ s_n_llhttp__internal__n_error_29: { + state->error = 0x7; + state->reason = "Expected CRLF"; + state->error_pos = (const char*) p; +@@ -13372,7 +13450,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_29: { ++ s_n_llhttp__internal__n_error_30: { + state->error = 0x9; + state->reason = "Expected CRLF after version"; + state->error_pos = (const char*) p; +@@ -13389,7 +13467,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_30: { ++ s_n_llhttp__internal__n_error_31: { + state->error = 0x9; + state->reason = "Invalid minor version"; + state->error_pos = (const char*) p; +@@ -13398,7 +13476,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_31: { ++ s_n_llhttp__internal__n_error_32: { + state->error = 0x9; + state->reason = "Expected dot"; + state->error_pos = (const char*) p; +@@ -13415,7 +13493,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_32: { ++ s_n_llhttp__internal__n_error_33: { + state->error = 0x9; + state->reason = "Invalid major version"; + state->error_pos = (const char*) p; +@@ -13424,7 +13502,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_34: { ++ s_n_llhttp__internal__n_error_35: { + state->error = 0x8; + state->reason = "Expected HTTP/"; + state->error_pos = (const char*) p; +@@ -13433,7 +13511,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_33: { ++ s_n_llhttp__internal__n_error_34: { + state->error = 0x8; + state->reason = "Expected SOURCE method for ICE/x.x request"; + state->error_pos = (const char*) p; +@@ -13445,7 +13523,7 @@ static llparse_state_t llhttp__internal__run( + s_n_llhttp__internal__n_invoke_is_equal_method_1: { + switch (llhttp__internal__c_is_equal_method_1(state, p, endp)) { + case 0: +- goto s_n_llhttp__internal__n_error_33; ++ goto s_n_llhttp__internal__n_error_34; + default: + goto s_n_llhttp__internal__n_req_http_major; + } +@@ -13520,7 +13598,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_35: { ++ s_n_llhttp__internal__n_error_36: { + state->error = 0x7; + state->reason = "Invalid char in url fragment start"; + state->error_pos = (const char*) p; +@@ -13580,7 +13658,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_36: { ++ s_n_llhttp__internal__n_error_37: { + state->error = 0x7; + state->reason = "Invalid char in url query"; + state->error_pos = (const char*) p; +@@ -13589,7 +13667,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_37: { ++ s_n_llhttp__internal__n_error_38: { + state->error = 0x7; + state->reason = "Invalid char in url path"; + state->error_pos = (const char*) p; +@@ -13700,7 +13778,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_38: { ++ s_n_llhttp__internal__n_error_39: { + state->error = 0x7; + state->reason = "Double @ in url"; + state->error_pos = (const char*) p; +@@ -13709,7 +13787,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_39: { ++ s_n_llhttp__internal__n_error_40: { + state->error = 0x7; + state->reason = "Unexpected char in url server"; + state->error_pos = (const char*) p; +@@ -13718,7 +13796,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_40: { ++ s_n_llhttp__internal__n_error_41: { + state->error = 0x7; + state->reason = "Unexpected char in url server"; + state->error_pos = (const char*) p; +@@ -13727,7 +13805,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_42: { ++ s_n_llhttp__internal__n_error_43: { + state->error = 0x7; + state->reason = "Unexpected char in url schema"; + state->error_pos = (const char*) p; +@@ -13736,7 +13814,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_43: { ++ s_n_llhttp__internal__n_error_44: { + state->error = 0x7; + state->reason = "Unexpected char in url schema"; + state->error_pos = (const char*) p; +@@ -13745,7 +13823,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_44: { ++ s_n_llhttp__internal__n_error_45: { + state->error = 0x7; + state->reason = "Unexpected start char in url"; + state->error_pos = (const char*) p; +@@ -13764,7 +13842,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_45: { ++ s_n_llhttp__internal__n_error_46: { + state->error = 0x6; + state->reason = "Expected space after method"; + state->error_pos = (const char*) p; +@@ -13781,7 +13859,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_53: { ++ s_n_llhttp__internal__n_error_54: { + state->error = 0x6; + state->reason = "Invalid method encountered"; + state->error_pos = (const char*) p; +@@ -13790,7 +13868,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_46: { ++ s_n_llhttp__internal__n_error_47: { + state->error = 0xd; + state->reason = "Response overflow"; + state->error_pos = (const char*) p; +@@ -13802,7 +13880,7 @@ static llparse_state_t llhttp__internal__run( + s_n_llhttp__internal__n_invoke_mul_add_status_code: { + switch (llhttp__internal__c_mul_add_status_code(state, p, endp, match)) { + case 1: +- goto s_n_llhttp__internal__n_error_46; ++ goto s_n_llhttp__internal__n_error_47; + default: + goto s_n_llhttp__internal__n_res_status_code; + } +@@ -13845,7 +13923,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_47: { ++ s_n_llhttp__internal__n_error_48: { + state->error = 0xd; + state->reason = "Invalid response status"; + state->error_pos = (const char*) p; +@@ -13862,7 +13940,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_48: { ++ s_n_llhttp__internal__n_error_49: { + state->error = 0x9; + state->reason = "Expected space after version"; + state->error_pos = (const char*) p; +@@ -13879,7 +13957,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_49: { ++ s_n_llhttp__internal__n_error_50: { + state->error = 0x9; + state->reason = "Invalid minor version"; + state->error_pos = (const char*) p; +@@ -13888,7 +13966,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_50: { ++ s_n_llhttp__internal__n_error_51: { + state->error = 0x9; + state->reason = "Expected dot"; + state->error_pos = (const char*) p; +@@ -13905,7 +13983,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_51: { ++ s_n_llhttp__internal__n_error_52: { + state->error = 0x9; + state->reason = "Invalid major version"; + state->error_pos = (const char*) p; +@@ -13914,7 +13992,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_54: { ++ s_n_llhttp__internal__n_error_55: { + state->error = 0x8; + state->reason = "Expected HTTP/"; + state->error_pos = (const char*) p; +@@ -13939,7 +14017,7 @@ static llparse_state_t llhttp__internal__run( + /* UNREACHABLE */; + abort(); + } +- s_n_llhttp__internal__n_error_52: { ++ s_n_llhttp__internal__n_error_53: { + state->error = 0x8; + state->reason = "Invalid word encountered"; + state->error_pos = (const char*) p; +diff --git a/test/parallel/test-http-multi-line-headers.js b/test/parallel/test-http-multi-line-headers.js +index 99c48cd..2381c17 100644 +--- a/test/parallel/test-http-multi-line-headers.js ++++ b/test/parallel/test-http-multi-line-headers.js +@@ -46,7 +46,8 @@ const server = net.createServer(function(conn) { + server.listen(0, common.mustCall(function() { + http.get({ + host: '127.0.0.1', +- port: this.address().port ++ port: this.address().port, ++ insecureHTTPParser: true + }, common.mustCall(function(res) { + assert.strictEqual(res.headers['content-type'], + 'text/plain; x-unix-mode=0600; name="hello.txt"'); +diff --git a/test/parallel/test-http-transfer-encoding-smuggling.js b/test/parallel/test-http-transfer-encoding-smuggling.js +index a6677b4..8e889cb 100644 +--- a/test/parallel/test-http-transfer-encoding-smuggling.js ++++ b/test/parallel/test-http-transfer-encoding-smuggling.js +@@ -71,10 +71,7 @@ const net = require('net'); + '', + ].join('\r\n'); + +- const server = http.createServer(common.mustCall((request, response) => { +- assert.notStrictEqual(request.url, '/admin'); +- response.end('hello world'); +- }), 1); ++ const server = http.createServer(common.mustNotCall()); + + server.listen(0, common.mustSucceed(() => { + const client = net.connect(server.address().port, 'localhost'); +-- +2.46.0 + diff --git a/CVE-2024-27983.patch b/CVE-2024-27983.patch new file mode 100644 index 0000000000000000000000000000000000000000..f17aa53b28efc3a481a89e1795ae82c1ab9da64a --- /dev/null +++ b/CVE-2024-27983.patch @@ -0,0 +1,34 @@ +From: RafaelGSS +Date: Tue, 26 Mar 2024 15:55:13 -0300 +Subject: CVE-2024-27983 ensure to close stream when destroying session + +Co-Authored-By: Anna Henningsen +PR-URL: https://github.com/nodejs-private/node-private/pull/561 +bug-hakerone: https://hackerone.com/reports/2319584 +Reviewed-By: Michael Dawson +Reviewed-By: Marco Ippolito +Reviewed-By: Matteo Collina +Reviewed-By: Benjamin Gruenbaum +CVE-ID: CVE-2024-27983 +origin: backport, https://github.com/nodejs/node/commit/0fb816dbccde955cd24acc1b16497a91fab507c8.patch +--- + src/node_http2.cc | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/node_http2.cc b/src/node_http2.cc +index 5156aa3..c441921 100644 +--- a/src/node_http2.cc ++++ b/src/node_http2.cc +@@ -590,6 +590,12 @@ Http2Session::Http2Session(Environment* env, + Http2Session::~Http2Session() { + CHECK_EQ(flags_ & SESSION_STATE_HAS_SCOPE, 0); + Debug(this, "freeing nghttp2 session"); ++ // Ensure that all `Http2Stream` instances and the memory they hold ++ // on to are destroyed before the nghttp2 session is. ++ for (const auto& [id, stream] : streams_) { ++ stream->Detach(); ++ } ++ streams_.clear(); + nghttp2_session_del(session_); + CHECK_EQ(current_nghttp2_memory_, 0); + } diff --git a/nodejs.spec b/nodejs.spec index 4b14072932a60b7eb5486ed6b9467832119c415d..566db286fc3603057115e8b20d4cbc06ffaf1516 100644 --- a/nodejs.spec +++ b/nodejs.spec @@ -1,5 +1,5 @@ %bcond_with bootstrap -%global baserelease 7 +%global baserelease 8 %{?!_pkgdocdir:%global _pkgdocdir %{_docdir}/%{name}-%{version}} %global nodejs_epoch 1 %global nodejs_major 12 @@ -105,6 +105,11 @@ Patch00027: CVE-2023-0464.patch Patch00028: CVE-2023-0465.patch # https://github.com/nghttp2/nghttp2/commit/72b4af6143681f528f1d237b21a9a7aee1738832 Patch00029: CVE-2023-44487.patch +Patch00030: CVE-2023-46809.patch +Patch00031: CVE-2024-22019.patch +Patch00032: CVE-2024-22025.patch +Patch00033: CVE-2024-27982.patch +Patch00034: CVE-2024-27983.patch BuildRequires: python3-devel BuildRequires: zlib-devel @@ -507,6 +512,9 @@ end %{_pkgdocdir}/npm/docs %changelog +* Thu Sep 19 2024 yaoxin - 1:12.22.11-8 +- Fix CVE-2023-46809,CVE-2024-22019,CVE-2024-22025,CVE-2024-27982 and CVE-2024-27983 + * Tue Feb 06 2024 yaoxin - 1:12.22.11-7 - Fix CVE-2023-44487