Skip to content

Commit

Permalink
http: validate HTTP version
Browse files Browse the repository at this point in the history
  • Loading branch information
ShogunPanda committed May 27, 2022
1 parent 75b4512 commit d245a5f
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 15 deletions.
64 changes: 50 additions & 14 deletions src/llhttp/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@ const NODES: ReadonlyArray<string> = [
'req_or_res_method',

'res_http_major',
'res_http_dot',
'res_http_minor',
'res_http_major_0',
'res_http_major_1',
'res_http_major_2',
'res_http_minor_0',
'res_http_minor_1',
'res_http_minor_2',
'res_http_end',
'res_status_code',
'res_status_code_otherwise',
Expand All @@ -40,8 +44,12 @@ const NODES: ReadonlyArray<string> = [
'req_spaces_before_url',
'req_http_start',
'req_http_major',
'req_http_dot',
'req_http_minor',
'req_http_major_0',
'req_http_major_1',
'req_http_major_2',
'req_http_minor_0',
'req_http_minor_1',
'req_http_minor_2',
'req_http_end',
'req_http_complete',

Expand Down Expand Up @@ -250,15 +258,29 @@ export class HTTP {
.otherwise(p.error(ERROR.INVALID_CONSTANT, 'Expected HTTP/'));

n('res_http_major')
.select(MAJOR, this.store('http_major', 'res_http_dot'))
.match('0', this.update('http_major', 0, 'res_http_major_0'))
.match('1', this.update('http_major', 1, 'res_http_major_1'))
.match('2', this.update('http_major', 2, 'res_http_major_2'))
.otherwise(p.error(ERROR.INVALID_VERSION, 'Invalid major version'));

n('res_http_major_0')
.match(['.', '.9'], this.update('http_minor', 9, 'res_http_end'))
.otherwise(p.error(ERROR.INVALID_VERSION, 'Invalid major version'));

n('res_http_dot')
.match('.', n('res_http_minor'))
n('res_http_major_1')
.match('.', n('res_http_minor_1'))
.otherwise(p.error(ERROR.INVALID_VERSION, 'Expected dot'));

n('res_http_major_2')
.match('.', n('res_http_minor_1'))
.otherwise(p.error(ERROR.INVALID_VERSION, 'Expected dot'));

n('res_http_minor')
.select(MINOR, this.store('http_minor', 'res_http_end'))
n('res_http_minor_1')
.select({0: 0, 1: 1}, this.store('http_minor', 'res_http_end'))
.otherwise(p.error(ERROR.INVALID_VERSION, 'Invalid minor version'));

n('res_http_minor_2')
.match('0', this.update('http_minor', 0, 'res_http_end'))
.otherwise(p.error(ERROR.INVALID_VERSION, 'Invalid minor version'));

n('res_http_end')
Expand Down Expand Up @@ -356,15 +378,29 @@ export class HTTP {
.otherwise(p.error(ERROR.INVALID_CONSTANT, 'Expected HTTP/'));

n('req_http_major')
.select(MAJOR, this.store('http_major', 'req_http_dot'))
.match('0', this.update('http_major', 0, 'req_http_major_0'))
.match('1', this.update('http_major', 1, 'req_http_major_1'))
.match('2', this.update('http_major', 2, 'req_http_major_2'))
.otherwise(p.error(ERROR.INVALID_VERSION, 'Invalid major version'));

n('req_http_dot')
.match('.', n('req_http_minor'))
n('req_http_major_0')
.match(['.', '.9'], this.update('http_minor', 9, 'req_http_end'))
.otherwise(p.error(ERROR.INVALID_VERSION, 'Invalid major version'));

n('req_http_major_1')
.match('.', n('req_http_minor_1'))
.otherwise(p.error(ERROR.INVALID_VERSION, 'Expected dot'));

n('req_http_major_2')
.match('.', n('req_http_minor_1'))
.otherwise(p.error(ERROR.INVALID_VERSION, 'Expected dot'));

n('req_http_minor')
.select(MINOR, this.store('http_minor', 'req_http_end'))
n('req_http_minor_1')
.select({0: 0, 1: 1}, this.store('http_minor', 'req_http_end'))
.otherwise(p.error(ERROR.INVALID_VERSION, 'Invalid minor version'));

n('req_http_minor_2')
.match('0', this.update('http_minor', 0, 'req_http_end'))
.otherwise(p.error(ERROR.INVALID_VERSION, 'Invalid minor version'));

n('req_http_end').otherwise(this.load('method', {
Expand Down
16 changes: 16 additions & 0 deletions test/request/invalid.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,19 @@ off=22 len=15 span[header_value]="www.example.com"
off=39 header_value complete
off=52 error code=10 reason="Invalid header token"
```

### Invalid HTTP version

<!-- meta={"type": "request", "noScan": true} -->
```http
GET / HTTP/5.6
```

```log
off=0 message begin
off=4 len=1 span[url]="/"
off=6 url complete
off=11 error code=9 reason="Invalid major version"
```
16 changes: 15 additions & 1 deletion test/response/invalid.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ HTTP/01.1 200 OK

```log
off=0 message begin
off=6 error code=9 reason="Expected dot"
off=6 error code=9 reason="Invalid major version"
```

### Extra digit in HTTP major version #2
Expand Down Expand Up @@ -106,3 +106,17 @@ off=21 header_field complete
off=22 len=1 span[header_value]="1"
off=24 error code=3 reason="Missing expected LF after header value"
```

### Invalid HTTP version

<!-- meta={"type": "response"} -->
```http
HTTP/5.6 200 OK
```

```log
off=0 message begin
off=5 error code=9 reason="Invalid major version"
```

0 comments on commit d245a5f

Please sign in to comment.