-
-
Notifications
You must be signed in to change notification settings - Fork 755
Off-by-one in 1.x urlencoded parameterCount breaks parsing arrays #715
Description
Discovered in expressjs/express#7135.
parameterCount has an off-by-one bug (returns 0 for "a=x", 1 for "a=x&b=y", ...). This in turn causes an array like "a[0]=1&a[1]=2&...&a[199]=200" to be parsed by qs with arrayLimit: 199.
This used to work, because arrayLimit: 199 would allow the index to be at most 199. qs@6.14.2 changed arrayLimit behaviour to instead restrict the array length (ljharb/qs#540 (comment), ljharb/qs@cfc108f, 6.14.2 changelog).
2.x uses a slightly different function and returns the real number of parameters.
More context on the differences: #652 (comment)
Environment information
Version: 1.20.4
Platform: Microsoft Windows NT 10.0.19045.0 x64
Node.js version: 25.8.2
Any other relevant information: When using public API, the problem can be observed only with qs >=6.14.2
What steps will reproduce the bug?
- Try parsing a large (>100 elements) array using extended urlencoded parser
Alternatively:
- Run
npm test, the following test will fail:
body-parser/test/urlencoded.js
Lines 167 to 185 in b849bd5
it('should parse array index notation with large array', function (done) { var str = 'f[0]=0' for (var i = 1; i < 500; i++) { str += '&f[' + i + ']=' + i.toString(16) } request(this.server) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send(str) .expect(function (res) { var obj = JSON.parse(res.text) assert.strictEqual(Object.keys(obj).length, 1) assert.strictEqual(Array.isArray(obj.f), true) assert.strictEqual(obj.f.length, 500) }) .expect(200, done) })