Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix chunk extensions quoted-string value parsing #253

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/llhttp/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,17 @@ for (let i = 0x21; i <= 0xff; i++) {
}
}

export const HTAB_SP_VCHAR_OBS_TEXT: CharList = [ '\t', ' ' ];

// VCHAR: https://tools.ietf.org/html/rfc5234#appendix-B.1
for (let i = 0x21; i <= 0x7E; i++) {
HTAB_SP_VCHAR_OBS_TEXT.push(i);
}
// OBS_TEXT: https://datatracker.ietf.org/doc/html/rfc9110#name-collected-abnf
for (let i = 0x80; i <= 0xff; i++) {
HTAB_SP_VCHAR_OBS_TEXT.push(i);
}

export const MAJOR = NUM_MAP;
export const MINOR = MAJOR;

Expand Down
10 changes: 9 additions & 1 deletion src/llhttp/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Node = source.node.Node;
import {
CharList,
CONNECTION_TOKEN_CHARS, ERROR, FINISH, FLAGS, H_METHOD_MAP, HEADER_CHARS,
HEADER_STATE, HEX_MAP,
HEADER_STATE, HEX_MAP, HTAB_SP_VCHAR_OBS_TEXT,
LENIENT_FLAGS,
MAJOR, METHOD_MAP, METHODS, METHODS_HTTP, METHODS_ICE, METHODS_RTSP,
MINOR, NUM_MAP, QUOTED_STRING, SPECIAL_HEADERS,
Expand Down Expand Up @@ -94,6 +94,7 @@ const NODES: ReadonlyArray<string> = [
'chunk_extension_name',
'chunk_extension_value',
'chunk_extension_quoted_value',
'chunk_extension_quoted_value_quoted_pair',
'chunk_extension_quoted_value_done',
'chunk_data',
'chunk_data_almost_done',
Expand Down Expand Up @@ -989,10 +990,17 @@ export class HTTP {
.match('"', this.span.chunkExtensionValue.end(
onChunkExtensionValueCompleted(n('chunk_extension_quoted_value_done')),
))
.match('\\', n('chunk_extension_quoted_value_quoted_pair'))
.otherwise(this.span.chunkExtensionValue.end().skipTo(
p.error(ERROR.STRICT, 'Invalid character in chunk extensions quoted value'),
));

n('chunk_extension_quoted_value_quoted_pair')
.match(HTAB_SP_VCHAR_OBS_TEXT, n('chunk_extension_quoted_value'))
.otherwise(this.span.chunkExtensionValue.end().skipTo(
p.error(ERROR.STRICT, 'Invalid quoted-pair in chunk extensions quoted value'),
));

n('chunk_extension_quoted_value_done')
.match(';', n('chunk_extensions'))
.match('\r', n('chunk_size_almost_done'))
Expand Down
48 changes: 24 additions & 24 deletions test/request/transfer-encoding.md
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ off=98 error code=2 reason="Invalid character in chunk extensions"
POST /chunked_w_unicorns_after_length HTTP/1.1
Transfer-Encoding: chunked

5;ilovew3="I love; extensions";somuchlove="aretheseparametersfor";blah;foo=bar
5;ilovew3="I \"love\"; \\extensions\\";somuchlove="aretheseparametersfor";blah;foo=bar
hello
6;blahblah;blah
world
Expand All @@ -375,29 +375,29 @@ off=76 header_value complete
off=78 headers complete method=3 v=1/1 flags=208 content_length=0
off=80 len=7 span[chunk_extension_name]="ilovew3"
off=88 chunk_extension_name complete
off=88 len=20 span[chunk_extension_value]=""I love; extensions""
off=108 chunk_extension_value complete
off=109 len=10 span[chunk_extension_name]="somuchlove"
off=120 chunk_extension_name complete
off=120 len=23 span[chunk_extension_value]=""aretheseparametersfor""
off=143 chunk_extension_value complete
off=144 len=4 span[chunk_extension_name]="blah"
off=149 chunk_extension_name complete
off=149 len=3 span[chunk_extension_name]="foo"
off=153 chunk_extension_name complete
off=153 len=3 span[chunk_extension_value]="bar"
off=157 chunk_extension_value complete
off=158 chunk header len=5
off=158 len=5 span[body]="hello"
off=165 chunk complete
off=167 len=8 span[chunk_extension_name]="blahblah"
off=176 chunk_extension_name complete
off=176 len=4 span[chunk_extension_name]="blah"
off=181 chunk_extension_name complete
off=182 chunk header len=6
off=182 len=6 span[body]=" world"
off=190 chunk complete
off=193 chunk header len=0
off=88 len=28 span[chunk_extension_value]=""I \"love\"; \\extensions\\""
off=116 chunk_extension_value complete
off=117 len=10 span[chunk_extension_name]="somuchlove"
off=128 chunk_extension_name complete
off=128 len=23 span[chunk_extension_value]=""aretheseparametersfor""
off=151 chunk_extension_value complete
off=152 len=4 span[chunk_extension_name]="blah"
off=157 chunk_extension_name complete
off=157 len=3 span[chunk_extension_name]="foo"
off=161 chunk_extension_name complete
off=161 len=3 span[chunk_extension_value]="bar"
off=165 chunk_extension_value complete
off=166 chunk header len=5
off=166 len=5 span[body]="hello"
off=173 chunk complete
off=175 len=8 span[chunk_extension_name]="blahblah"
off=184 chunk_extension_name complete
off=184 len=4 span[chunk_extension_name]="blah"
off=189 chunk_extension_name complete
off=190 chunk header len=6
off=190 len=6 span[body]=" world"
off=198 chunk complete
off=201 chunk header len=0
```


Expand Down