Skip to content
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

querystring: allow querystring parse to handle __proto__ #6044

Closed
wants to merge 1 commit into from

Conversation

jasnell
Copy link
Member

@jasnell jasnell commented Apr 4, 2016

Pull Request check-list

  • Does make -j8 test (UNIX) or vcbuild test nosign (Windows) pass with
    this change (including linting)?
  • Is the commit message formatted according to [CONTRIBUTING.md][0]?
  • If this change fixes a bug (or a performance problem), is a regression
    test (or a benchmark) included?

Affected core subsystem(s)

querystring

Description of change

Per #5642, using querystring.parse to parse 'a=b&__proto__=1' causes the __proto__ to be swallowed and ignored. This works around the limitation by temporarily setting the prototype of the parsed obj to null during the parse, then setting it back before returning.

The rest of the existing implementation remains the same.

Fixes: #5642

/cc @mscdex @WebReflection

@jasnell jasnell added the querystring Issues and PRs related to the built-in querystring module. label Apr 4, 2016
@jasnell jasnell changed the title querystring: all querystring parse to handle __proto__ querystring: allow querystring parse to handle __proto__ Apr 4, 2016
@jasnell jasnell force-pushed the querystring-proto branch 2 times, most recently from f9b4060 to e0fb8dd Compare April 4, 2016 22:53
@mscdex
Copy link
Contributor

mscdex commented Apr 4, 2016

If this change is going to be made, wouldn't it be simpler to just use Object.create(null) instead of {} for obj? What is the performance difference if there is any?

@jasnell
Copy link
Member Author

jasnell commented Apr 4, 2016

Interesting... using Object.create(null) gives a slight performance edge in a simple benchmark:

'use strict';
var common = require('../common.js');
var querystring = require('querystring');
var v8 = require('v8');

var bench = common.createBenchmark(main, {
  n: [1e6],
});

function main(conf) {
  var n = conf.n | 0;

  const input = 'a=b&__proto__=1';

  v8.setFlagsFromString('--allow_natives_syntax');
  querystring.parse(input);
  eval('%OptimizeFunctionOnNextCall(querystring.parse)');
  querystring.parse(input);

  var i;
  bench.start();
  for (i = 0; i < n; i += 1)
    querystring.parse(input);
  bench.end(n);
}

@jasnell
Copy link
Member Author

jasnell commented Apr 4, 2016

@mscdex ... updated to use Object.create(null).

if (typeof qs !== 'string' || qs.length === 0) {
return obj;
return {};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we comfortable with this inconsistency?

@mscdex
Copy link
Contributor

mscdex commented Apr 4, 2016

FWIW using Object.create(null) was already discussed in the linked issue and has its own set of performance regressions. Is this solution (out of the other suggested solutions in the linked issue) and its performance something that everyone can (mostly) agree on?

@mscdex mscdex added the semver-major PRs that contain breaking changes and should be released in the next major version. label Apr 4, 2016
@Fishrock123
Copy link
Contributor

👎 Unless we can see that Object.create(null) isn't orders of magnitude slower. :/

@mscdex
Copy link
Contributor

mscdex commented Apr 5, 2016

@Fishrock123 It still is.

@jasnell I think I may have found a solution that doesn't cause a performance regression and may even provide somewhat of a performance boost.

@jasnell
Copy link
Member Author

jasnell commented Apr 5, 2016

Sigh, every time I benchmark this I'm getting different results. I'll switch it back to {} for now. What's the alternative you found @mscdex ?

Per nodejs#5642, using querystring.parse to parse 'a=b&__proto__=1'
causes the `__proto__` to be swallowed and ignored. This
works around the limitation by temporarily setting the
prototype of the parsed obj to null during the parse, then
setting it back before returning.

Fixes: nodejs#5642
@jasnell jasnell force-pushed the querystring-proto branch from 71d02ad to 8abf8a8 Compare April 5, 2016 05:13
@WebReflection
Copy link
Contributor

since you never know how much optimization could be done, I'd go for:

// begin
var obj = Object.setPrototypeOf({}, null);
// ... rest of the code ...
// end
return Object.setPrototypeOf(obj, Object.prototype);

at least it couldn't go more compact than that, and the returned value from setPrototypeOf doens't get wasted.

}

var obj = {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not Object.create(null)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, had this open for a while and GH refreshed so I just now noticed this was already discussed.

@Sinewyk
Copy link

Sinewyk commented Apr 5, 2016

Related: #6055

@jasnell
Copy link
Member Author

jasnell commented Apr 7, 2016

Closing in favor of @mscdex's #6055

@jasnell jasnell closed this Apr 7, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
querystring Issues and PRs related to the built-in querystring module. semver-major PRs that contain breaking changes and should be released in the next major version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

querystring module swallows __proto__ key
6 participants