-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
http: setEncoding error for incoming socket connections #19344
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this actually something also defined in any of these?
RFC 7230, HTTP/1.1: Message Syntax and Routing
RFC 7231, HTTP/1.1: Semantics and Content
RFC 7232, HTTP/1.1: Conditional Requests
RFC 7233, HTTP/1.1: Range Requests
RFC 7234, HTTP/1.1: Caching
RFC 7235, HTTP/1.1: Authentication
lib/internal/errors.js
Outdated
@@ -728,6 +728,9 @@ E('ERR_HTTP2_STREAM_SELF_DEPENDENCY', | |||
E('ERR_HTTP2_UNSUPPORTED_PROTOCOL', 'protocol "%s" is unsupported.', Error); | |||
E('ERR_HTTP_HEADERS_SENT', | |||
'Cannot %s headers after they are sent to the client', Error); | |||
E('ERR_HTTP_INCOMING_SOCKET_ENCODING', | |||
'Incoming socket encoding is not allowed (RFC 2616)', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please change this to e.g., Changing the incoming socket encoding is not possible (see RFC 2616)
?.
doc/api/errors.md
Outdated
### ERR_HTTP_INCOMING_SOCKET_ENCODING | ||
|
||
An attempt was made to manipulate the encoding of an incoming request packet. | ||
This is not allowed (RFC2616). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: This is forbidden by [RFC 2616](https://www.ietf.org/rfc/rfc2616.txt)
.
@BridgeAR yes, the use of US-ASCII is noted frequently throughout the RFC articles but the most important is:
Should I reference RFC7230 instead? |
I do believe RFC7230 - RFC7240 is a collection of updates to RFC2616 |
5ccd427
to
a1e62c5
Compare
772e6b0
to
63a72c6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
doc/api/errors.md
Outdated
### ERR_HTTP_INCOMING_SOCKET_ENCODING | ||
|
||
An attempt was made to manipulate the encoding of an incoming request packet. | ||
This is forbidden by [RFC7230 Section 3](https://tools.ietf.org/html/rfc7230#section-3) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: this is longer than 80 characters and the linter is probably going to complain about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It did - I wasn't sure what to do because it was a URL and it appears to be the only one in the docs that is written this way. Still thought it was worth referencing the RFC because this is such a specific issue with a specific fix with no other options - so I left it
This looks better 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe what we generally do is put all link URLs at the end of the file, and then reference the label here. The same could be done here.
@@ -683,6 +685,10 @@ function onSocketPause() { | |||
} | |||
} | |||
|
|||
function socketSetEncoding() { | |||
throw new ERR_HTTP_INCOMING_SOCKET_ENCODING('setEncoding'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no dynamic argument in this error, so there is no need to pass through any arguments.
Looks like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While the code changes look good to me, the reason why setEncoding('utf8')
doesn't work is not because HTTP always uses US-ASCII, but rather that Node.js C++ internals are not prepared to deal with strings rather than Buffers. In fact, the same crash would happen if one uses setEncoding('ascii')
.
As such, the error message and the documentation should be amended, to something to the sense of "changing it is not supported" rather than not allowed by the RFC.
doc/api/errors.md
Outdated
### ERR_HTTP_INCOMING_SOCKET_ENCODING | ||
|
||
An attempt was made to manipulate the encoding of an incoming request packet. | ||
This is forbidden by [RFC7230 Section 3](https://tools.ietf.org/html/rfc7230#section-3) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe what we generally do is put all link URLs at the end of the file, and then reference the label here. The same could be done here.
@@ -383,6 +384,7 @@ function connectionListenerInternal(server, socket) { | |||
|
|||
// Override on to unconsume on `data`, `readable` listeners | |||
socket.on = socketOnWrap; | |||
socket.setEncoding = socketSetEncoding; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: either a comment or a new line here would be nice, since this line isn't related to
// Override on to unconsume on `data`, `readable` listeners
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, because I didn't see that done in errors.md
(aside from internal page links) I tried to follow suit. I'll update that.
63a72c6
to
52684df
Compare
@apapirovski, @BridgeAR Go ahead! |
Firstly, new TSC member @TimothyGu, congrats!! Second, with the release date coming up, I'd like to get these test passing. By the looks of it, the build errors are due to linting problems. When I run More
And for
@BridgeAR, @TimothyGu, @apapirovski any suggestions? |
lib/_http_server.js
Outdated
@@ -383,6 +384,8 @@ function connectionListenerInternal(server, socket) { | |||
|
|||
// Override on to unconsume on `data`, `readable` listeners | |||
socket.on = socketOnWrap; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this line has trailing space (should be 0 length).
const server = http.createServer().listen(0, connectToServer); | ||
|
||
server.on('connection', (socket) => { | ||
common.expectsError(() => socket.setEncoding(''), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you might still be testing the old setEncoding
here. I think you might be better off just using normal request callback and then using req.socket.setEncoding
.
But maybe I'm missing something else that's off about this... not sure. It is throwing an AssertionError though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That req
part isn't an option in the 'connection'
event. Are you saying to test with an incoming request after the 'connection'
? This wouldn't throw an error because the request is parsed by then.
For example:
http.createServer( ( req, res ) => {
req.socket.setEncoding( 'utf8' );
res.end( 'OK' );
} )
is ok to do. It's only "pre-parse" attempts to manipulate the incoming buffer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, you can ignore me. It's complaining about the fact that you're providing an argument to the error, as mentioned above by @BridgeAR.
But if you're saying it's ok then this PR isn't quite valid because calling that req.socket.setEncoding('utf8')
will still throw as things exist currently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But also this isn't strictly correct. It's definitely not OK to call req.socket.setEncoding
until after the end
event. (Basically: it's never OK within the lifetime of its usefulness so we might as well just throw unconditionally.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. Do you know any history behind setEncoding
and how it even came about?
Right now I override setEncoding
in the connectionListenerInternal
method. This causes a fatal error as detailed in #18118. Are you recommending we remove it completely from the HTTP module?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, we got our wires crossed. I'm just referencing this bit...
Are you saying to test with an incoming request after the 'connection'? This wouldn't throw an error because the request is parsed by then.
It would throw throughout the requests lifetime. Sockets that are used for http should never have their encoding changed. I'm just saying that this is also correct behaviour.
To simplify: I'm fine with this PR as is except for the linting issue and the one pointed out by @BridgeAR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment from @addaleax on the original PR suggests there are other uses of setEncoding
when possibly responding to a protocol change request or connection upgrade requests.
There's a slight chance it could be necessary when using abstract protocols such as Internet Printing Protocol/1.0
or some other media protocols. Although, as I discussed in that PR, this should not be allowed in the scope of HTTP. HTTP in, HTTP out.
So this would require moving socket.setEncoding = socketSetEncoding;
to somewhere in the httpSocketSetup
method or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@iSkore Thanks for the link. I might need to think about this more. I think that particular use-case would be addressed by resetting the socket setEncoding
back within the the upgrade
code path but there might be others that are not addressed. This might also affect how modules like ws
operate. Let me do some research or feel free to do it yourself — but it seems like this PR will need to be updated to account for at least upgrade
, if not more.
Just fyi... it's too late to get this in to 10.0.0. Unless they're super critical, there will be no more majors pulled in. |
@jasnell - gotcha. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just marking with red X so no one accidentally lands this. The use-case of upgrade
or sockets that are both http
and, say, WS, needs to be addressed.
@apapirovski no problem. Some more information for discussion. My interpretation of RFC 7230 Section 6.7 is that regardless of the upgrade request, the response must still be in US-ASCII. Example:
Although, it also states:
That protocol could have a different encoding... but RFC20 ASCII format for Network Interchange implores those protocols be in ASCII. As for handling WebSocket Protocol RFC 6455
So in the case of an upgrade to WebSocket Protocol, the HTTP response and WS interchange should both be ASCII. With all that TL;DR information said - this PR fixes a fatal issue detailed in #18118. Should the fix to the |
ping @iSkore @apapirovski what's the status on this? |
ping @iSkore Are you planning to move this one forward, or can this be closed? It has been abandoned for months now. |
@ryzokuken this is held up on me. We need to solve the problem of sockets that are upgraded or otherwise detached from |
@apapirovski, following up on this. Should I add in a check like "if socket is getting upgraded, allow |
This is currently on the 11.0.0 milestone, but as a semver-major, even if it lands right now, it's going to miss the release. Removing it from the 11.0.0 milestone. |
/ping @apapirovski |
Closing this due to inactivity. Please reopen if needed. |
applied updates from previous pull-requests to disallow socket.setEncoding before a http connection is parsed. wrapped socket.setEncoding to throw an error. previously resulted in a fatal error Fixes: nodejs#18118 Ref: nodejs#18178 Ref: nodejs#19344
Applied updates from previous pull-requests to disallow socket.setEncoding before a http connection is parsed. Wrapped `socket.setEncoding` to throw an error. This previously resulted in a fatal error. PR-URL: nodejs#33405 Fixes: nodejs#18118 Refs: nodejs#18178 Refs: nodejs#19344 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
socket.setEncoding
to not allow encoding changes on incoming socket connectionsERR_HTTP_INCOMING_SOCKET_ENCODING
Original PR-URL: #18178 (new pull request made due to git issues)
Because HTTP must be in US-ASCII, this function should either not be allowed, or should throw a standard
stackTrace error
if invoked on an incoming packet.Currently, the process encounters a fatal v8 error and crashes.
error report detailed in: issue #18118
Ref: #18178
Fixes: #18118
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
_http_server
doc
errors
tests