(timing variant of the Bleichenbacher attack against PKCS#1 v1.5 padding) - (Medium) (CVE-2023-46809, bsc#1219997) * CVE-2024-22019.patch: http: Reading unprocessed HTTP request with unbounded chunk extension allows DoS attacks- (High) (CVE-2024-22019, bsc#1219993) * CVE-2024-22025.patch: fix Denial of Service by resource exhaustion in fetch() brotli decoding (CVE-2024-22025, bsc#1220014) * CVE-2024-24758.patch: ignore proxy-authorization headers (CVE-2024-24758, bsc#1220017) * CVE-2024-24806.patch: fix improper domain lookup that potentially leads to SSRF attacks (CVE-2024-24806, bsc#1220053) - CVE-2023-38552.patch: Integrity checks according to policies can be circumvented (CVE-2023-38552, bsc#1216272) - CVE-2023-39333.patch, wasm-fixture.tar.gz: Code injection via WebAssembly export names (CVE-2023-39333, bsc#1216273) - CVE-2023-45143.patch: undici Security Release (CVE-2023-45143, bsc#1216205) - nodejs.keyring: include new releaser keys OBS-URL: https://build.opensuse.org/package/show/devel:languages:nodejs/nodejs16?expand=0&rev=100
528 lines
17 KiB
Diff
528 lines
17 KiB
Diff
Index: node-v16.20.2/deps/llhttp/CMakeLists.txt
|
|
===================================================================
|
|
--- node-v16.20.2.orig/deps/llhttp/CMakeLists.txt
|
|
+++ node-v16.20.2/deps/llhttp/CMakeLists.txt
|
|
@@ -1,7 +1,7 @@
|
|
cmake_minimum_required(VERSION 3.5.1)
|
|
cmake_policy(SET CMP0069 NEW)
|
|
|
|
-project(llhttp VERSION 6.0.11)
|
|
+project(llhttp VERSION 6.1.0)
|
|
include(GNUInstallDirs)
|
|
|
|
set(CMAKE_C_STANDARD 99)
|
|
Index: node-v16.20.2/deps/llhttp/include/llhttp.h
|
|
===================================================================
|
|
--- node-v16.20.2.orig/deps/llhttp/include/llhttp.h
|
|
+++ node-v16.20.2/deps/llhttp/include/llhttp.h
|
|
@@ -2,8 +2,8 @@
|
|
#define INCLUDE_LLHTTP_H_
|
|
|
|
#define LLHTTP_VERSION_MAJOR 6
|
|
-#define LLHTTP_VERSION_MINOR 0
|
|
-#define LLHTTP_VERSION_PATCH 11
|
|
+#define LLHTTP_VERSION_MINOR 1
|
|
+#define LLHTTP_VERSION_PATCH 0
|
|
|
|
#ifndef LLHTTP_STRICT_MODE
|
|
# define LLHTTP_STRICT_MODE 0
|
|
@@ -349,6 +349,9 @@ 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` */
|
|
Index: node-v16.20.2/deps/llhttp/src/api.c
|
|
===================================================================
|
|
--- node-v16.20.2.orig/deps/llhttp/src/api.c
|
|
+++ node-v16.20.2/deps/llhttp/src/api.c
|
|
@@ -355,6 +355,13 @@ int llhttp__on_chunk_header(llhttp_t* s,
|
|
}
|
|
|
|
|
|
+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);
|
|
Index: node-v16.20.2/deps/llhttp/src/llhttp.c
|
|
===================================================================
|
|
--- node-v16.20.2.orig/deps/llhttp/src/llhttp.c
|
|
+++ node-v16.20.2/deps/llhttp/src/llhttp.c
|
|
@@ -340,6 +340,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,
|
|
@@ -539,6 +541,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);
|
|
@@ -1226,8 +1232,7 @@ static llparse_state_t llhttp__internal_
|
|
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;
|
|
@@ -1236,6 +1241,34 @@ static llparse_state_t llhttp__internal_
|
|
/* 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) {
|
|
@@ -1246,13 +1279,9 @@ static llparse_state_t llhttp__internal_
|
|
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;
|
|
@@ -6074,6 +6103,24 @@ static llparse_state_t llhttp__internal_
|
|
/* 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";
|
|
@@ -8441,6 +8488,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,
|
|
@@ -8635,6 +8684,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);
|
|
@@ -9299,8 +9352,7 @@ static llparse_state_t llhttp__internal_
|
|
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;
|
|
@@ -9309,6 +9361,34 @@ static llparse_state_t llhttp__internal_
|
|
/* 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) {
|
|
@@ -9319,13 +9399,9 @@ static llparse_state_t llhttp__internal_
|
|
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;
|
|
@@ -13951,6 +14027,24 @@ static llparse_state_t llhttp__internal_
|
|
/* 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";
|
|
Index: node-v16.20.2/doc/api/errors.md
|
|
===================================================================
|
|
--- node-v16.20.2.orig/doc/api/errors.md
|
|
+++ node-v16.20.2/doc/api/errors.md
|
|
@@ -3043,6 +3043,18 @@ malconfigured clients, if more than 8 Ki
|
|
HTTP parsing will abort without a request or response object being created, and
|
|
an `Error` with this code will be emitted.
|
|
|
|
+<a id="HPE_CHUNK_EXTENSIONS_OVERFLOW"></a>
|
|
+
|
|
+### `HPE_CHUNK_EXTENSIONS_OVERFLOW`
|
|
+
|
|
+<!-- YAML
|
|
+added: REPLACEME
|
|
+-->
|
|
+
|
|
+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.
|
|
+
|
|
<a id="HPE_UNEXPECTED_CONTENT_LENGTH"></a>
|
|
|
|
### `HPE_UNEXPECTED_CONTENT_LENGTH`
|
|
Index: node-v16.20.2/test/parallel/test-http-chunk-extensions-limit.js
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ node-v16.20.2/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'
|
|
+ );
|
|
+ });
|
|
+}
|
|
Index: node-v16.20.2/tools/update-llhttp.sh
|
|
===================================================================
|
|
--- node-v16.20.2.orig/tools/update-llhttp.sh
|
|
+++ node-v16.20.2/tools/update-llhttp.sh
|
|
@@ -59,5 +59,5 @@ echo ""
|
|
echo "Please git add llhttp, commit the new version:"
|
|
echo ""
|
|
echo "$ git add -A deps/llhttp"
|
|
-echo "$ git commit -m \"deps: update nghttp2 to $LLHTTP_VERSION\""
|
|
+echo "$ git commit -m \"deps: update llhttp to $LLHTTP_VERSION\""
|
|
echo ""
|
|
Index: node-v16.20.2/lib/_http_server.js
|
|
===================================================================
|
|
--- node-v16.20.2.orig/lib/_http_server.js
|
|
+++ node-v16.20.2/lib/_http_server.js
|
|
@@ -706,6 +706,11 @@ const requestHeaderFieldsTooLargeRespons
|
|
`HTTP/1.1 431 ${STATUS_CODES[431]}\r\n` +
|
|
'Connection: close\r\n\r\n', '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);
|
|
@@ -719,6 +724,9 @@ function socketOnError(e) {
|
|
case 'HPE_HEADER_OVERFLOW':
|
|
response = requestHeaderFieldsTooLargeResponse;
|
|
break;
|
|
+ case 'HPE_CHUNK_EXTENSIONS_OVERFLOW':
|
|
+ response = requestChunkExtensionsTooLargeResponse;
|
|
+ break;
|
|
case 'ERR_HTTP_REQUEST_TIMEOUT':
|
|
response = requestTimeoutResponse;
|
|
break;
|
|
Index: node-v16.20.2/src/node_http_parser.cc
|
|
===================================================================
|
|
--- node-v16.20.2.orig/src/node_http_parser.cc
|
|
+++ node-v16.20.2/src/node_http_parser.cc
|
|
@@ -79,6 +79,8 @@ const uint32_t kOnExecute = 5;
|
|
const uint32_t kOnTimeout = 6;
|
|
// 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;
|
|
|
|
const uint32_t kLenientNone = 0;
|
|
const uint32_t kLenientHeaders = 1 << 0;
|
|
@@ -206,6 +208,7 @@ class Parser : public AsyncWrap, public
|
|
|
|
int on_message_begin() {
|
|
num_fields_ = num_values_ = 0;
|
|
+ chunk_extensions_nread_ = 0;
|
|
url_.Reset();
|
|
status_message_.Reset();
|
|
header_parsing_start_time_ = uv_hrtime();
|
|
@@ -443,9 +446,22 @@ class Parser : public AsyncWrap, public
|
|
return 0;
|
|
}
|
|
|
|
- // 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;
|
|
}
|
|
|
|
@@ -887,6 +903,7 @@ class Parser : public AsyncWrap, public
|
|
const char* current_buffer_data_;
|
|
bool pending_pause_ = false;
|
|
uint64_t header_nread_ = 0;
|
|
+ uint64_t chunk_extensions_nread_ = 0;
|
|
uint64_t max_http_header_size_;
|
|
uint64_t headers_timeout_;
|
|
uint64_t header_parsing_start_time_ = 0;
|
|
@@ -921,6 +938,7 @@ const llhttp_settings_t Parser::settings
|
|
Proxy<DataCall, &Parser::on_header_field>::Raw,
|
|
Proxy<DataCall, &Parser::on_header_value>::Raw,
|
|
Proxy<Call, &Parser::on_headers_complete>::Raw,
|
|
+ Proxy<DataCall, &Parser::on_chunk_extension>::Raw,
|
|
Proxy<DataCall, &Parser::on_body>::Raw,
|
|
Proxy<Call, &Parser::on_message_complete>::Raw,
|
|
Proxy<Call, &Parser::on_chunk_header>::Raw,
|