Skip to content

Commit ac9b8f7

Browse files
mscdexBethGriggs
authored andcommittedMar 20, 2019
http: fix error check in Execute()
`http_parser_execute(..., nullptr, 0)` returns either `0` or `1`. The expectation is that no error must be returned if it is `0`, and if it is `1` - a `Error` object must be returned back to user. The introduction of `llhttp` and the refactor that happened during it accidentally removed the error-returning code. This commit reverts it back to its original state. Backport-PR-URL: #25938 Fix: #24585 PR-URL: #24738 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 1d86261 commit ac9b8f7

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed
 

‎src/node_http_parser.cc

+28-2
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,28 @@ class Parser : public AsyncWrap {
621621
size_t nparsed =
622622
http_parser_execute(&parser_, &settings, data, len);
623623

624-
Save();
624+
enum http_errno err = HTTP_PARSER_ERRNO(&parser_);
625+
626+
// Finish()
627+
if (data == nullptr) {
628+
// `http_parser_execute()` returns either `0` or `1` when `len` is 0
629+
// (part of the finishing sequence).
630+
CHECK_EQ(len, 0);
631+
switch (nparsed) {
632+
case 0:
633+
err = HPE_OK;
634+
break;
635+
case 1:
636+
nparsed = 0;
637+
break;
638+
default:
639+
UNREACHABLE();
640+
}
641+
642+
// Regular Execute()
643+
} else {
644+
Save();
645+
}
625646

626647
// Unassign the 'buffer_' variable
627648
current_buffer_.Clear();
@@ -635,7 +656,7 @@ class Parser : public AsyncWrap {
635656
Local<Integer> nparsed_obj = Integer::New(env()->isolate(), nparsed);
636657
// If there was a parse error in one of the callbacks
637658
// TODO(bnoordhuis) What if there is an error on EOF?
638-
if (!parser_.upgrade && nparsed != len) {
659+
if (!parser_.upgrade && err != HPE_OK) {
639660
enum http_errno err = HTTP_PARSER_ERRNO(&parser_);
640661

641662
Local<Value> e = Exception::Error(env()->parse_error_string());
@@ -646,6 +667,11 @@ class Parser : public AsyncWrap {
646667

647668
return scope.Escape(e);
648669
}
670+
671+
// No return value is needed for `Finish()`
672+
if (data == nullptr) {
673+
return scope.Escape(Local<Value>());
674+
}
649675
return scope.Escape(nparsed_obj);
650676
}
651677

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
require('../common');
3+
const common = require('../common');
44
const assert = require('assert');
55
const { spawnSync } = require('child_process');
66
const http = require('http');
@@ -9,3 +9,16 @@ assert.strictEqual(http.maxHeaderSize, 8 * 1024);
99
const child = spawnSync(process.execPath, ['--max-http-header-size=10', '-p',
1010
'http.maxHeaderSize']);
1111
assert.strictEqual(+child.stdout.toString().trim(), 10);
12+
13+
{
14+
const server = http.createServer(common.mustNotCall());
15+
server.listen(0, common.mustCall(() => {
16+
http.get({
17+
port: server.address().port,
18+
headers: { foo: 'x'.repeat(http.maxHeaderSize + 1) }
19+
}, common.mustNotCall()).once('error', common.mustCall((err) => {
20+
assert.strictEqual(err.code, 'ECONNRESET');
21+
server.close();
22+
}));
23+
}));
24+
}

0 commit comments

Comments
 (0)
Please sign in to comment.