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_parser: assert on incoming argument's type #12288

Closed
wants to merge 1 commit into
base: master
from

Conversation

@gireeshpunathil
Member

gireeshpunathil commented Apr 9, 2017

Unchecked argument conversion in Parser::Consume crashes node
in an slightly undesirable manner - 'unreachable code' in parser.

Make sure we validate the incoming type at the earliest point.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • commit message follows commit guidelines
Affected core subsystem(s)

http_parser

@gireeshpunathil

This comment has been minimized.

Show comment
Hide comment
@gireeshpunathil

gireeshpunathil Apr 9, 2017

Member

Reference: #12178

Member

gireeshpunathil commented Apr 9, 2017

Reference: #12178

Show outdated Hide outdated src/node_http_parser.cc
@cjihrig

Can you add a test please. The current changes LGTM though.

@aqrln

This comment has been minimized.

Show comment
Hide comment
@aqrln

aqrln Apr 9, 2017

Member

@gireeshpunathil do you mind adding the Fixes: https://github.com/nodejs/node/issues/12178 field to the commit message? Thanks!

Member

aqrln commented Apr 9, 2017

@gireeshpunathil do you mind adding the Fixes: https://github.com/nodejs/node/issues/12178 field to the commit message? Thanks!

Show outdated Hide outdated src/node_http_parser.cc
@gireeshpunathil

This comment has been minimized.

Show comment
Hide comment
@gireeshpunathil

gireeshpunathil Apr 10, 2017

Member

@aqrln - thanks, added the Fixes: tag into the commit message.
Regarding the CHECK (expr && msg) semantics: I found it less useful - this is how the output appears:

out/Release/node[2219]: ../src/node_http_parser.cc:476:static void node::Parser::Consume(const FunctionCallbackInfo<v8::Value> &): Assertion `args[0]->IsExternal() && "parser.consume requires a stream argument."' failed.
 1: node::Abort() [./node]
...

Member

gireeshpunathil commented Apr 10, 2017

@aqrln - thanks, added the Fixes: tag into the commit message.
Regarding the CHECK (expr && msg) semantics: I found it less useful - this is how the output appears:

out/Release/node[2219]: ../src/node_http_parser.cc:476:static void node::Parser::Consume(const FunctionCallbackInfo<v8::Value> &): Assertion `args[0]->IsExternal() && "parser.consume requires a stream argument."' failed.
 1: node::Abort() [./node]
...

@gireeshpunathil

This comment has been minimized.

Show comment
Hide comment
@gireeshpunathil

gireeshpunathil Apr 10, 2017

Member

@cjihrig - thanks. I have this test program (sort of a regression test) devised - based on the Exception throwing logic, but @bnoordhuis 's latest suggestion (use of CHECK) would mean that we would assert in C++ land on failure, and managing / validating that in a JS test case seems hacky. Any suggestions?

#cat test/parallel/test-http-parser-consume.js
'use strict';
const common = require('../common');
const assert = require('assert');
const http = require('http');
const spawn = require('child_process').spawn;

if (process.argv[2] === 'child') {
  var server = http.createServer(function(q, s) {
    s.end('hello');
  });

  server.listen(common.PORT, function(s) {
    var rr = http.get('http://localhost:' + common.PORT, function(d) {
      try {
        rr.parser.consume(0);
      }
      catch(e) {
        e.toString().includes('parser.consume requires a stream argument.');
        process.exit(0);
      }
    });
  });
}
else {
  const child = spawn(process.argv[0], [process.argv[1], 'child']);
  child.on('stdout', function(d) {
    console.log(d.toString());
  });
  child.on('stderr', function(d) {
    console.log(d.toString());
  });
  child.on('exit', common.mustCall(function(code, signal) {
    assert(signal === null && code === 0, 'Parser::Consume should not crash the process.');
  }));
}
Member

gireeshpunathil commented Apr 10, 2017

@cjihrig - thanks. I have this test program (sort of a regression test) devised - based on the Exception throwing logic, but @bnoordhuis 's latest suggestion (use of CHECK) would mean that we would assert in C++ land on failure, and managing / validating that in a JS test case seems hacky. Any suggestions?

#cat test/parallel/test-http-parser-consume.js
'use strict';
const common = require('../common');
const assert = require('assert');
const http = require('http');
const spawn = require('child_process').spawn;

if (process.argv[2] === 'child') {
  var server = http.createServer(function(q, s) {
    s.end('hello');
  });

  server.listen(common.PORT, function(s) {
    var rr = http.get('http://localhost:' + common.PORT, function(d) {
      try {
        rr.parser.consume(0);
      }
      catch(e) {
        e.toString().includes('parser.consume requires a stream argument.');
        process.exit(0);
      }
    });
  });
}
else {
  const child = spawn(process.argv[0], [process.argv[1], 'child']);
  child.on('stdout', function(d) {
    console.log(d.toString());
  });
  child.on('stderr', function(d) {
    console.log(d.toString());
  });
  child.on('exit', common.mustCall(function(code, signal) {
    assert(signal === null && code === 0, 'Parser::Consume should not crash the process.');
  }));
}
Show outdated Hide outdated src/node_http_parser.cc
@gireeshpunathil

This comment has been minimized.

Show comment
Hide comment
@gireeshpunathil

gireeshpunathil Apr 10, 2017

Member

@cjihrig - Added a test case to capture this. As it stands out, the evolved change in the parser code means that the process now ABRTs as opposed to a SEGV in response to bad input, and the test is made to validate this fact only.

Member

gireeshpunathil commented Apr 10, 2017

@cjihrig - Added a test case to capture this. As it stands out, the evolved change in the parser code means that the process now ABRTs as opposed to a SEGV in response to bad input, and the test is made to validate this fact only.

Show outdated Hide outdated test/parallel/test-http-parser-consume.js
Show outdated Hide outdated test/parallel/test-http-parser-consume.js
Show outdated Hide outdated test/parallel/test-http-parser-consume.js
Show outdated Hide outdated test/parallel/test-http-parser-consume.js
Show outdated Hide outdated test/parallel/test-http-parser-consume.js
Show outdated Hide outdated test/parallel/test-http-parser-consume.js
Show outdated Hide outdated test/parallel/test-http-parser-consume.js
@DemiMarie

This comment has been minimized.

Show comment
Hide comment
@DemiMarie

DemiMarie Apr 10, 2017

Why is crashing with SIGABRT okay? I would expect that this should throw a proper JS exception.

DemiMarie commented Apr 10, 2017

Why is crashing with SIGABRT okay? I would expect that this should throw a proper JS exception.

@addaleax

This comment has been minimized.

Show comment
Hide comment
@addaleax

addaleax Apr 10, 2017

Member

Why is crashing with SIGABRT okay? I would expect that this should throw a proper JS exception.

I think the reasoning of @bnoordhuis (and maybe others) here is that this kind of crash can only be produced by messing with or accessing what Node.js would consider its internals, here by using .parser.

I talked about this again with @bengl a few days ago, and while we agreed that we would like to see a more un-crashable Node, we also agreed that Ben has a good and valid point here.

Member

addaleax commented Apr 10, 2017

Why is crashing with SIGABRT okay? I would expect that this should throw a proper JS exception.

I think the reasoning of @bnoordhuis (and maybe others) here is that this kind of crash can only be produced by messing with or accessing what Node.js would consider its internals, here by using .parser.

I talked about this again with @bengl a few days ago, and while we agreed that we would like to see a more un-crashable Node, we also agreed that Ben has a good and valid point here.

@cjihrig

One more nit in the test, but LGTM if the CI passes.

Show outdated Hide outdated test/parallel/test-http-parser-consume.js
Show outdated Hide outdated test/parallel/test-http-parser-consume.js
Show outdated Hide outdated test/parallel/test-http-parser-consume.js
@jasnell

This comment has been minimized.

Show comment
Hide comment
@jasnell

jasnell Apr 12, 2017

Member

what would the semver level be on this? Should we treat this as a major?

Member

jasnell commented Apr 12, 2017

what would the semver level be on this? Should we treat this as a major?

@addaleax

This comment has been minimized.

Show comment
Hide comment
@addaleax

addaleax Apr 12, 2017

Member

what would the semver level be on this? Should we treat this as a major?

I’d say it’s semver-patch at most (semver-doesntreallymatteranyway if we’re being honest). It turns one kind of hard crash into another, and practically speaking it’s not a bug that gets triggered unless you are actively looking into how to crash node.

Member

addaleax commented Apr 12, 2017

what would the semver level be on this? Should we treat this as a major?

I’d say it’s semver-patch at most (semver-doesntreallymatteranyway if we’re being honest). It turns one kind of hard crash into another, and practically speaking it’s not a bug that gets triggered unless you are actively looking into how to crash node.

@aqrln

aqrln approved these changes Apr 12, 2017

LGTM. Now that the PR performs a CHECK() instead of throwing an exception like it did initially, I'm not sure that it fixes #12178 in a way one would expect it to, so, arguably, it's worth changing "Fixes:" to "Refs:". That said, I'm +1 for this change.

CI: https://ci.nodejs.org/job/node-test-pull-request/7350/

Show outdated Hide outdated test/parallel/test-http-parser-consume.js
Show outdated Hide outdated test/parallel/test-http-parser-consume.js
@aqrln

node-test-linter on CI doesn't seem to be happy. Can you please fix the linter errors?

@jasnell

I'm good with semver-patch. LGTM with the linting issue fixed.

@santigimeno

LGTM with a couple of suggestions

Show outdated Hide outdated test/parallel/test-http-parser-consume.js
Show outdated Hide outdated test/parallel/test-http-parser-consume.js
@gireeshpunathil

This comment has been minimized.

Show comment
Hide comment
@gireeshpunathil

gireeshpunathil Apr 12, 2017

Member

@aqrln - linter error is fixed. Windows build also failed but seem to be caused by infra issues - can you please check?

Member

gireeshpunathil commented Apr 12, 2017

@aqrln - linter error is fixed. Windows build also failed but seem to be caused by infra issues - can you please check?

@aqrln

This comment has been minimized.

Show comment
Hide comment
@aqrln

aqrln Apr 12, 2017

Member

@gireeshpunathil nope, not an infra issue, as far as I can see:

not ok 142 parallel/test-http-parser-consume
  ---
  duration_ms: 0.431
  severity: fail
  stack: |-
    c:\workspace\node-test-binary-windows\RUN_SUBSET\3\VS_VERSION\vcbt2015\label\win10\Release\node.exe: src\node_http_parser.cc:496: Assertion `args[0]->IsExternal()' failed.
    
    assert.js:82
      throw new assert.AssertionError({
      ^
    AssertionError: parser.consume should not crash, but ended with null
        at ChildProcess.<anonymous> (c:\workspace\node-test-binary-windows\RUN_SUBSET\3\VS_VERSION\vcbt2015\label\win10\test\parallel\test-http-parser-consume.js:23:5)
        at ChildProcess.<anonymous> (c:\workspace\node-test-binary-windows\RUN_SUBSET\3\VS_VERSION\vcbt2015\label\win10\test\common.js:461:15)
        at emitTwo (events.js:125:13)
        at ChildProcess.emit (events.js:213:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:208:12)
  ...
Member

aqrln commented Apr 12, 2017

@gireeshpunathil nope, not an infra issue, as far as I can see:

not ok 142 parallel/test-http-parser-consume
  ---
  duration_ms: 0.431
  severity: fail
  stack: |-
    c:\workspace\node-test-binary-windows\RUN_SUBSET\3\VS_VERSION\vcbt2015\label\win10\Release\node.exe: src\node_http_parser.cc:496: Assertion `args[0]->IsExternal()' failed.
    
    assert.js:82
      throw new assert.AssertionError({
      ^
    AssertionError: parser.consume should not crash, but ended with null
        at ChildProcess.<anonymous> (c:\workspace\node-test-binary-windows\RUN_SUBSET\3\VS_VERSION\vcbt2015\label\win10\test\parallel\test-http-parser-consume.js:23:5)
        at ChildProcess.<anonymous> (c:\workspace\node-test-binary-windows\RUN_SUBSET\3\VS_VERSION\vcbt2015\label\win10\test\common.js:461:15)
        at emitTwo (events.js:125:13)
        at ChildProcess.emit (events.js:213:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:208:12)
  ...
@gireeshpunathil

This comment has been minimized.

Show comment
Hide comment
@gireeshpunathil

gireeshpunathil Apr 12, 2017

Member

@aqrln - thanks for checking, I will debug.

Member

gireeshpunathil commented Apr 12, 2017

@aqrln - thanks for checking, I will debug.

Show outdated Hide outdated test/parallel/test-http-parser-consume.js
@aqrln

This comment has been minimized.

Show comment
Hide comment
@aqrln

aqrln Apr 12, 2017

Member

@gireeshpunathil no problem. CI results are public, by the way, so you can check things like that yourself, just follow the link :)

Member

aqrln commented Apr 12, 2017

@gireeshpunathil no problem. CI results are public, by the way, so you can check things like that yourself, just follow the link :)

@gireeshpunathil

This comment has been minimized.

Show comment
Hide comment
@gireeshpunathil

gireeshpunathil Apr 13, 2017

Member

Looks like Windows handles Abort exit codes and signals differently - please see abort codes
Addressed a change to that effect, by squeezing both the asserts into one and tested.

Member

gireeshpunathil commented Apr 13, 2017

Looks like Windows handles Abort exit codes and signals differently - please see abort codes
Addressed a change to that effect, by squeezing both the asserts into one and tested.

@gireeshpunathil

This comment has been minimized.

Show comment
Hide comment
@gireeshpunathil

gireeshpunathil Jun 3, 2017

Member

Soft ping to reviewers - are we fine with this?

Member

gireeshpunathil commented Jun 3, 2017

Soft ping to reviewers - are we fine with this?

@bnoordhuis

Can you put the test in test/abort?

Show outdated Hide outdated test/parallel/test-http-parser-consume.js
@gireeshpunathil

This comment has been minimized.

Show comment
Hide comment
@gireeshpunathil

gireeshpunathil Jun 4, 2017

Member

all clear - a CI please!
/cc @nodejs/http
/cc @nodejs/platform-windows

Member

gireeshpunathil commented Jun 4, 2017

all clear - a CI please!
/cc @nodejs/http
/cc @nodejs/platform-windows

@santigimeno

This comment has been minimized.

Show comment
Hide comment
@gibfahn

This comment has been minimized.

Show comment
Hide comment
@gibfahn

gibfahn Jun 4, 2017

Member

cc/ @nodejs/http
cc/ @nodejs/platform-windows

Duplicating cc/ as I don't think it works if you're not a collaborator (which is a bit of a pain).

Member

gibfahn commented Jun 4, 2017

cc/ @nodejs/http
cc/ @nodejs/platform-windows

Duplicating cc/ as I don't think it works if you're not a collaborator (which is a bit of a pain).

@gireeshpunathil

This comment has been minimized.

Show comment
Hide comment
@gireeshpunathil

gireeshpunathil Jun 4, 2017

Member

o! I never knew - thanks @gibfahn for that. I would have (and had) spent a lot of cc/ stuff thinking that someone will get a mail.

Member

gireeshpunathil commented Jun 4, 2017

o! I never knew - thanks @gibfahn for that. I would have (and had) spent a lot of cc/ stuff thinking that someone will get a mail.

@refack

This comment has been minimized.

Show comment
Hide comment
@refack

refack Jun 4, 2017

Member

Duplicating cc/ as I don't think it works if you're not a collaborator (which is a bit of a pain).

fullish GitHub 🤦‍♂️

Member

refack commented Jun 4, 2017

Duplicating cc/ as I don't think it works if you're not a collaborator (which is a bit of a pain).

fullish GitHub 🤦‍♂️

@refack

This comment has been minimized.

Show comment
Hide comment
@refack

refack Jun 4, 2017

Member

o! I never knew - thanks @gibfahn for that. I would have (and had) spent a lot of cc/ stuff thinking that someone will get a mail.

I think the limitation it's just for @nodejs/ teams. This and a inability to assign issues to everyone, IMHO very foolish.

Member

refack commented Jun 4, 2017

o! I never knew - thanks @gibfahn for that. I would have (and had) spent a lot of cc/ stuff thinking that someone will get a mail.

I think the limitation it's just for @nodejs/ teams. This and a inability to assign issues to everyone, IMHO very foolish.

@refack refack self-assigned this Jun 4, 2017

@refack

refack approved these changes Jun 4, 2017

2 nits

Show outdated Hide outdated test/abort/test-http-parser-consume.js
Show outdated Hide outdated test/abort/test-http-parser-consume.js
http_parser: assert on incoming argument's type
Unchecked argument conversion in Parser::Consume crashes node
in an slightly undesirable manner - 'unreachable code' in parser.

Make sure we validate the incoming type at the earliest point.

Refs: #12178
@refack

This comment has been minimized.

Show comment
Hide comment
@refack

refack Jun 5, 2017

Member

Pre-land CI: https://ci.nodejs.org/job/node-test-commit/10368/
@gireeshpunathil did you address all comments (I couldn't find @sam-github's)?

Member

refack commented Jun 5, 2017

Pre-land CI: https://ci.nodejs.org/job/node-test-commit/10368/
@gireeshpunathil did you address all comments (I couldn't find @sam-github's)?

@sam-github

This comment has been minimized.

Show comment
Hide comment
@sam-github

sam-github Jun 5, 2017

Member

I can't find mine either, ignore me please.

Member

sam-github commented Jun 5, 2017

I can't find mine either, ignore me please.

@gibfahn

This comment has been minimized.

Show comment
Hide comment
@gibfahn

gibfahn Jun 5, 2017

Member

(I couldn't find @sam-github's)?

#12288 (comment)

Member

gibfahn commented Jun 5, 2017

(I couldn't find @sam-github's)?

#12288 (comment)

refack added a commit to refack/node that referenced this pull request Jun 5, 2017

http: assert parser.consume argument's type
Unchecked argument conversion in Parser::Consume crashes node
in an slightly undesirable manner - 'unreachable code' in parser.

Make sure we validate the incoming type at the earliest point.

PR-URL: nodejs#12288
Fixes: nodejs#12178
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Refael Ackermann <refack@gmail.com>
@refack

This comment has been minimized.

Show comment
Hide comment
@refack

refack Jun 5, 2017

Member

landed in efab784

Member

refack commented Jun 5, 2017

landed in efab784

@refack refack closed this Jun 5, 2017

@refack

This comment has been minimized.

Show comment
Hide comment
@refack
Member

refack commented Jun 5, 2017

jasnell added a commit that referenced this pull request Jun 7, 2017

http: assert parser.consume argument's type
Unchecked argument conversion in Parser::Consume crashes node
in an slightly undesirable manner - 'unreachable code' in parser.

Make sure we validate the incoming type at the earliest point.

PR-URL: #12288
Fixes: #12178
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Refael Ackermann <refack@gmail.com>

@gibfahn gibfahn referenced this pull request Jun 15, 2017

Closed

Auditing for 6.11.1 #230

2 of 3 tasks complete
@MylesBorins

This comment has been minimized.

Show comment
Hide comment
@MylesBorins

MylesBorins Jul 17, 2017

Member

Should this land on v6.x?

Member

MylesBorins commented Jul 17, 2017

Should this land on v6.x?

@MylesBorins

This comment has been minimized.

Show comment
Hide comment
@MylesBorins
Member

MylesBorins commented Aug 14, 2017

ping

@addaleax

This comment has been minimized.

Show comment
Hide comment
@addaleax
Member

addaleax commented Aug 14, 2017

MylesBorins added a commit that referenced this pull request Sep 19, 2017

http: assert parser.consume argument's type
Unchecked argument conversion in Parser::Consume crashes node
in an slightly undesirable manner - 'unreachable code' in parser.

Make sure we validate the incoming type at the earliest point.

PR-URL: #12288
Fixes: #12178
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Refael Ackermann <refack@gmail.com>

@MylesBorins MylesBorins referenced this pull request Sep 20, 2017

Merged

v6.11.4 proposal #15506

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment