Skip to content

Commit 3fe3bc9

Browse files
indutnyBridgeAR
authored andcommitted
http: fix error return in Finish()
`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. Fix: #24585 PR-URL: #24738 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 085f5b6 commit 3fe3bc9

File tree

2 files changed

+55
-4
lines changed

2 files changed

+55
-4
lines changed

src/node_http_parser.cc

+28-4
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,10 @@ class Parser : public AsyncWrap, public StreamListener {
491491
ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
492492

493493
CHECK(parser->current_buffer_.IsEmpty());
494-
parser->Execute(nullptr, 0);
494+
Local<Value> ret = parser->Execute(nullptr, 0);
495+
496+
if (!ret.IsEmpty())
497+
args.GetReturnValue().Set(ret);
495498
}
496499

497500

@@ -684,11 +687,28 @@ class Parser : public AsyncWrap, public StreamListener {
684687
}
685688
#else /* !NODE_EXPERIMENTAL_HTTP */
686689
size_t nread = http_parser_execute(&parser_, &settings, data, len);
687-
if (data != nullptr) {
690+
err = HTTP_PARSER_ERRNO(&parser_);
691+
692+
// Finish()
693+
if (data == nullptr) {
694+
// `http_parser_execute()` returns either `0` or `1` when `len` is 0
695+
// (part of the finishing sequence).
696+
CHECK_EQ(len, 0);
697+
switch (nread) {
698+
case 0:
699+
err = HPE_OK;
700+
break;
701+
case 1:
702+
nread = 0;
703+
break;
704+
default:
705+
UNREACHABLE();
706+
}
707+
708+
// Regular Execute()
709+
} else {
688710
Save();
689711
}
690-
691-
err = HTTP_PARSER_ERRNO(&parser_);
692712
#endif /* NODE_EXPERIMENTAL_HTTP */
693713

694714
// Unassign the 'buffer_' variable
@@ -738,6 +758,10 @@ class Parser : public AsyncWrap, public StreamListener {
738758
return scope.Escape(e);
739759
}
740760

761+
// No return value is needed for `Finish()`
762+
if (data == nullptr) {
763+
return scope.Escape(Local<Value>());
764+
}
741765
return scope.Escape(nread_obj);
742766
}
743767

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const net = require('net');
5+
const http = require('http');
6+
const assert = require('assert');
7+
8+
const str = 'GET / HTTP/1.1\r\n' +
9+
'Content-Length:';
10+
11+
12+
const server = http.createServer(common.mustNotCall());
13+
server.on('clientError', common.mustCall((err, socket) => {
14+
assert(/^Parse Error/.test(err.message));
15+
assert.strictEqual(err.code, 'HPE_INVALID_EOF_STATE');
16+
socket.destroy();
17+
}, 1));
18+
server.listen(0, () => {
19+
const client = net.connect({ port: server.address().port }, () => {
20+
client.on('data', common.mustNotCall());
21+
client.on('end', common.mustCall(() => {
22+
server.close();
23+
}));
24+
client.write(str);
25+
client.end();
26+
});
27+
});

0 commit comments

Comments
 (0)