parent
2a884631f6
commit
d0565f54c7
@ -0,0 +1,198 @@
|
||||
From ebfb5d982de56d8bbc87db8448e8d35a883202d3 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Insogna <paolo@cowtech.it>
|
||||
Date: Tue, 29 Oct 2024 09:29:50 +0000
|
||||
Subject: [PATCH] fix: Do not allow OBS fold in headers by default.
|
||||
|
||||
Upstream backport: https://github.com/nodejs/llhttp/pull/348
|
||||
---
|
||||
src/llhttp/http.ts | 13 +++--
|
||||
test/request/connection.md | 4 +-
|
||||
test/request/invalid.md | 85 ++++++++++++++++++++++++++++++
|
||||
test/request/sample.md | 2 +-
|
||||
test/request/transfer-encoding.md | 2 +-
|
||||
test/response/transfer-encoding.md | 2 +-
|
||||
6 files changed, 98 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/llhttp/http.ts b/src/llhttp/http.ts
|
||||
index d0bfd48..40eff4c 100644
|
||||
--- a/src/llhttp/http.ts
|
||||
+++ b/src/llhttp/http.ts
|
||||
@@ -827,11 +827,14 @@ export class HTTP {
|
||||
'Missing expected LF after header value'));
|
||||
|
||||
n('header_value_lws')
|
||||
- .peek([ ' ', '\t' ],
|
||||
- this.load('header_state', {
|
||||
- [HEADER_STATE.TRANSFER_ENCODING_CHUNKED]:
|
||||
- this.resetHeaderState(span.headerValue.start(n('header_value_start'))),
|
||||
- }, span.headerValue.start(n('header_value_start'))))
|
||||
+ .peek(
|
||||
+ [ ' ', '\t' ],
|
||||
+ this.testLenientFlags(LENIENT_FLAGS.HEADERS, {
|
||||
+ 1: this.load('header_state', {
|
||||
+ [HEADER_STATE.TRANSFER_ENCODING_CHUNKED]:
|
||||
+ this.resetHeaderState(span.headerValue.start(n('header_value_start'))),
|
||||
+ }, span.headerValue.start(n('header_value_start'))),
|
||||
+ }, p.error(ERROR.INVALID_HEADER_TOKEN, 'Unexpected whitespace after header value')))
|
||||
.otherwise(this.setHeaderFlags(onHeaderValueComplete));
|
||||
|
||||
const checkTrailing = this.testFlags(FLAGS.TRAILING, {
|
||||
diff --git a/test/request/connection.md b/test/request/connection.md
|
||||
index a03242e..68ed3e0 100644
|
||||
--- a/test/request/connection.md
|
||||
+++ b/test/request/connection.md
|
||||
@@ -374,7 +374,7 @@ off=75 message complete
|
||||
|
||||
### Multiple tokens with folding
|
||||
|
||||
-<!-- meta={"type": "request"} -->
|
||||
+<!-- meta={"type": "request-lenient-headers"} -->
|
||||
```http
|
||||
GET /demo HTTP/1.1
|
||||
Host: example.com
|
||||
@@ -465,7 +465,7 @@ off=75 error code=22 reason="Pause on CONNECT/Upgrade"
|
||||
|
||||
### Multiple tokens with folding, LWS, and CRLF
|
||||
|
||||
-<!-- meta={"type": "request"} -->
|
||||
+<!-- meta={"type": "request-lenient-headers"} -->
|
||||
```http
|
||||
GET /demo HTTP/1.1
|
||||
Connection: keep-alive, \r\n upgrade
|
||||
diff --git a/test/request/invalid.md b/test/request/invalid.md
|
||||
index 8eadacf..0d3b36e 100644
|
||||
--- a/test/request/invalid.md
|
||||
+++ b/test/request/invalid.md
|
||||
@@ -583,4 +583,89 @@ off=122 len=3 span[header_value]="ghi"
|
||||
off=126 header_value complete
|
||||
off=127 chunk complete
|
||||
off=127 message complete
|
||||
+```
|
||||
+
|
||||
+### Spaces before headers
|
||||
+
|
||||
+<!-- meta={ "type": "request" } -->
|
||||
+
|
||||
+```http
|
||||
+POST /hello HTTP/1.1
|
||||
+Host: localhost
|
||||
+Foo: bar
|
||||
+ Content-Length: 38
|
||||
+
|
||||
+GET /bye HTTP/1.1
|
||||
+Host: localhost
|
||||
+
|
||||
+
|
||||
+```
|
||||
+
|
||||
+```log
|
||||
+off=0 message begin
|
||||
+off=0 len=4 span[method]="POST"
|
||||
+off=4 method complete
|
||||
+off=5 len=6 span[url]="/hello"
|
||||
+off=12 url complete
|
||||
+off=17 len=3 span[version]="1.1"
|
||||
+off=20 version complete
|
||||
+off=22 len=4 span[header_field]="Host"
|
||||
+off=27 header_field complete
|
||||
+off=28 len=9 span[header_value]="localhost"
|
||||
+off=39 header_value complete
|
||||
+off=39 len=3 span[header_field]="Foo"
|
||||
+off=43 header_field complete
|
||||
+off=44 len=3 span[header_value]="bar"
|
||||
+off=49 error code=10 reason="Unexpected whitespace after header value"
|
||||
+```
|
||||
+
|
||||
+### Spaces before headers (lenient)
|
||||
+
|
||||
+<!-- meta={ "type": "request-lenient-headers" } -->
|
||||
+
|
||||
+```http
|
||||
+POST /hello HTTP/1.1
|
||||
+Host: localhost
|
||||
+Foo: bar
|
||||
+ Content-Length: 38
|
||||
+
|
||||
+GET /bye HTTP/1.1
|
||||
+Host: localhost
|
||||
+
|
||||
+
|
||||
+```
|
||||
+
|
||||
+```log
|
||||
+off=0 message begin
|
||||
+off=0 len=4 span[method]="POST"
|
||||
+off=4 method complete
|
||||
+off=5 len=6 span[url]="/hello"
|
||||
+off=12 url complete
|
||||
+off=17 len=3 span[version]="1.1"
|
||||
+off=20 version complete
|
||||
+off=22 len=4 span[header_field]="Host"
|
||||
+off=27 header_field complete
|
||||
+off=28 len=9 span[header_value]="localhost"
|
||||
+off=39 header_value complete
|
||||
+off=39 len=3 span[header_field]="Foo"
|
||||
+off=43 header_field complete
|
||||
+off=44 len=3 span[header_value]="bar"
|
||||
+off=49 len=19 span[header_value]=" Content-Length: 38"
|
||||
+off=70 header_value complete
|
||||
+off=72 headers complete method=3 v=1/1 flags=0 content_length=0
|
||||
+off=72 message complete
|
||||
+off=72 reset
|
||||
+off=72 message begin
|
||||
+off=72 len=3 span[method]="GET"
|
||||
+off=75 method complete
|
||||
+off=76 len=4 span[url]="/bye"
|
||||
+off=81 url complete
|
||||
+off=86 len=3 span[version]="1.1"
|
||||
+off=89 version complete
|
||||
+off=91 len=4 span[header_field]="Host"
|
||||
+off=96 header_field complete
|
||||
+off=97 len=9 span[header_value]="localhost"
|
||||
+off=108 header_value complete
|
||||
+off=110 headers complete method=1 v=1/1 flags=0 content_length=0
|
||||
+off=110 message complete
|
||||
```
|
||||
\ No newline at end of file
|
||||
diff --git a/test/request/sample.md b/test/request/sample.md
|
||||
index f0a5d44..de2ceb9 100644
|
||||
--- a/test/request/sample.md
|
||||
+++ b/test/request/sample.md
|
||||
@@ -540,7 +540,7 @@ off=61 message complete
|
||||
|
||||
See nodejs/test/parallel/test-http-headers-obstext.js
|
||||
|
||||
-<!-- meta={"type": "request"} -->
|
||||
+<!-- meta={"type": "request-lenient-headers"} -->
|
||||
```http
|
||||
GET / HTTP/1.1
|
||||
X-SSL-Nonsense: -----BEGIN CERTIFICATE-----
|
||||
diff --git a/test/request/transfer-encoding.md b/test/request/transfer-encoding.md
|
||||
index 0f839bc..b1b523d 100644
|
||||
--- a/test/request/transfer-encoding.md
|
||||
+++ b/test/request/transfer-encoding.md
|
||||
@@ -893,7 +893,7 @@ off=51 error code=12 reason="Invalid character in chunk size"
|
||||
|
||||
## Invalid OBS fold after chunked value
|
||||
|
||||
-<!-- meta={"type": "request" } -->
|
||||
+<!-- meta={"type": "request-lenient-headers" } -->
|
||||
```http
|
||||
PUT /url HTTP/1.1
|
||||
Transfer-Encoding: chunked
|
||||
diff --git a/test/response/transfer-encoding.md b/test/response/transfer-encoding.md
|
||||
index e1fd10a..0f54c72 100644
|
||||
--- a/test/response/transfer-encoding.md
|
||||
+++ b/test/response/transfer-encoding.md
|
||||
@@ -370,7 +370,7 @@ off=101 error code=2 reason="Invalid character in chunk extensions quoted value"
|
||||
|
||||
## Invalid OBS fold after chunked value
|
||||
|
||||
-<!-- meta={"type": "response" } -->
|
||||
+<!-- meta={"type": "response-lenient-headers" } -->
|
||||
```http
|
||||
HTTP/1.1 200 OK
|
||||
Transfer-Encoding: chunked
|
||||
--
|
||||
2.47.0
|
||||
|
Loading…
Reference in new issue