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: https://github.com/nodejs/node/pull/24738 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
3fb627bead
commit
175164e5d1
@ -491,7 +491,10 @@ class Parser : public AsyncWrap, public StreamListener {
|
|||||||
ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
|
ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
|
||||||
|
|
||||||
CHECK(parser->current_buffer_.IsEmpty());
|
CHECK(parser->current_buffer_.IsEmpty());
|
||||||
parser->Execute(nullptr, 0);
|
Local<Value> ret = parser->Execute(nullptr, 0);
|
||||||
|
|
||||||
|
if (!ret.IsEmpty())
|
||||||
|
args.GetReturnValue().Set(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -684,11 +687,28 @@ class Parser : public AsyncWrap, public StreamListener {
|
|||||||
}
|
}
|
||||||
#else /* !NODE_EXPERIMENTAL_HTTP */
|
#else /* !NODE_EXPERIMENTAL_HTTP */
|
||||||
size_t nread = http_parser_execute(&parser_, &settings, data, len);
|
size_t nread = http_parser_execute(&parser_, &settings, data, len);
|
||||||
if (data != nullptr) {
|
err = HTTP_PARSER_ERRNO(&parser_);
|
||||||
|
|
||||||
|
// Finish()
|
||||||
|
if (data == nullptr) {
|
||||||
|
// `http_parser_execute()` returns either `0` or `1` when `len` is 0
|
||||||
|
// (part of the finishing sequence).
|
||||||
|
CHECK_EQ(len, 0);
|
||||||
|
switch (nread) {
|
||||||
|
case 0:
|
||||||
|
err = HPE_OK;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
nread = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regular Execute()
|
||||||
|
} else {
|
||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
err = HTTP_PARSER_ERRNO(&parser_);
|
|
||||||
#endif /* NODE_EXPERIMENTAL_HTTP */
|
#endif /* NODE_EXPERIMENTAL_HTTP */
|
||||||
|
|
||||||
// Unassign the 'buffer_' variable
|
// Unassign the 'buffer_' variable
|
||||||
@ -738,6 +758,10 @@ class Parser : public AsyncWrap, public StreamListener {
|
|||||||
return scope.Escape(e);
|
return scope.Escape(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No return value is needed for `Finish()`
|
||||||
|
if (data == nullptr) {
|
||||||
|
return scope.Escape(Local<Value>());
|
||||||
|
}
|
||||||
return scope.Escape(nread_obj);
|
return scope.Escape(nread_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
27
test/parallel/test-http-parser-finish-error.js
Normal file
27
test/parallel/test-http-parser-finish-error.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common');
|
||||||
|
const net = require('net');
|
||||||
|
const http = require('http');
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
const str = 'GET / HTTP/1.1\r\n' +
|
||||||
|
'Content-Length:';
|
||||||
|
|
||||||
|
|
||||||
|
const server = http.createServer(common.mustNotCall());
|
||||||
|
server.on('clientError', common.mustCall((err, socket) => {
|
||||||
|
assert(/^Parse Error/.test(err.message));
|
||||||
|
assert.strictEqual(err.code, 'HPE_INVALID_EOF_STATE');
|
||||||
|
socket.destroy();
|
||||||
|
}, 1));
|
||||||
|
server.listen(0, () => {
|
||||||
|
const client = net.connect({ port: server.address().port }, () => {
|
||||||
|
client.on('data', common.mustNotCall());
|
||||||
|
client.on('end', common.mustCall(() => {
|
||||||
|
server.close();
|
||||||
|
}));
|
||||||
|
client.write(str);
|
||||||
|
client.end();
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user