Skip to content

Commit 8abf8a8

Browse files
committed
querystring: allow querystring parse to handle __proto__
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. Fixes: #5642
1 parent f739a12 commit 8abf8a8

File tree

3 files changed

+43
-3
lines changed

3 files changed

+43
-3
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict';
2+
var common = require('../common.js');
3+
var querystring = require('querystring');
4+
var v8 = require('v8');
5+
6+
var bench = common.createBenchmark(main, {
7+
n: [1e6],
8+
});
9+
10+
function main(conf) {
11+
var n = conf.n | 0;
12+
13+
const input = 'a=b&__proto__=1';
14+
15+
v8.setFlagsFromString('--allow_natives_syntax');
16+
querystring.parse(input);
17+
eval('%OptimizeFunctionOnNextCall(querystring.parse)');
18+
querystring.parse(input);
19+
20+
var i;
21+
bench.start();
22+
for (i = 0; i < n; i += 1)
23+
querystring.parse(input);
24+
bench.end(n);
25+
}

lib/querystring.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,12 +212,13 @@ QueryString.parse = QueryString.decode = function(qs, sep, eq, options) {
212212
sep = sep || '&';
213213
eq = eq || '=';
214214

215-
const obj = {};
216-
217215
if (typeof qs !== 'string' || qs.length === 0) {
218-
return obj;
216+
return {};
219217
}
220218

219+
var obj = {};
220+
Object.setPrototypeOf(obj, null);
221+
221222
if (typeof sep !== 'string')
222223
sep += '';
223224

@@ -387,6 +388,7 @@ QueryString.parse = QueryString.decode = function(qs, sep, eq, options) {
387388
}
388389
}
389390

391+
Object.setPrototypeOf(obj, Object.prototype);
390392
return obj;
391393
};
392394

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* eslint-disable no-proto */
2+
'use strict';
3+
4+
require('../common');
5+
const assert = require('assert');
6+
const qs = require('querystring');
7+
8+
const obj = qs.parse('a=b&__proto__=1');
9+
10+
assert.equal(obj.a, 'b');
11+
assert.equal(obj.__proto__, 1);
12+
assert(typeof Object.getPrototypeOf(obj) === 'object');
13+
assert.strictEqual(Object.getPrototypeOf(obj), Object.prototype);

0 commit comments

Comments
 (0)