fix: correct off-by-one error in parameterCount#716
Open
abhu85 wants to merge 1 commit intoexpressjs:1.xfrom
Open
fix: correct off-by-one error in parameterCount#716abhu85 wants to merge 1 commit intoexpressjs:1.xfrom
abhu85 wants to merge 1 commit intoexpressjs:1.xfrom
Conversation
The `parameterCount` function was counting `&` characters but returning that count directly. Since the number of parameters equals the number of `&` characters plus one, this caused an off-by-one error. For example, with `a[0]=1&a[1]=2&...&a[199]=200` (200 parameters): - Before: returned 199 (number of `&` chars) - After: returns 200 (actual parameter count) This bug became visible with qs@6.14.2 which changed `arrayLimit` to restrict array length instead of max index. With the buggy count, large arrays would be converted to objects instead of arrays. - Fix `parameterCount` to return `count + 1` - Add test case for array parsing with 110 elements Fixes expressjs#715
krzysdz
reviewed
Mar 30, 2026
Comment on lines
+509
to
+533
|
|
||
| it('should correctly count parameters for array parsing', function (done) { | ||
| // Test for off-by-one bug fix (issue #715) | ||
| // With 110 array elements, there are 110 parameters (109 & chars) | ||
| // Before fix: parameterCount returned 109, arrayLimit was 109 | ||
| // After fix: parameterCount returns 110, arrayLimit is 110 | ||
| var server = createServer({ extended: true, parameterLimit: 200 }) | ||
| var arrayParams = Array.from({ length: 110 }, function (_, i) { | ||
| return 'a[' + i + ']=' + (i + 1) | ||
| }).join('&') | ||
|
|
||
| request(server) | ||
| .post('/') | ||
| .type('form') | ||
| .send(arrayParams) | ||
| .expect(function (res) { | ||
| // The body should contain an array 'a' with 110 elements | ||
| // If parameterCount returns 109 (bug), arrayLimit would be 109, | ||
| // and qs would convert indices >= 109 to object keys | ||
| var body = JSON.parse(res.text) | ||
| assert.ok(Array.isArray(body.a), 'should have array "a", got: ' + res.text.substring(0, 200)) | ||
| assert.strictEqual(body.a.length, 110, 'array should have 110 elements') | ||
| }) | ||
| .expect(200, done) | ||
| }) |
There was a problem hiding this comment.
There already is a test that verifies this
body-parser/test/urlencoded.js
Lines 167 to 185 in b849bd5
Author
|
Thanks for pointing that out. I see the existing test at L167-185 with 500 elements. I added my test because I wanted to verify the specific off-by-one fix, but you're right that the existing test should theoretically catch this too since:
Does the existing test currently fail on main without this fix? If so, I'm happy to remove my test as redundant. If there's something causing it to pass despite the bug, my test provides additional coverage. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fix off-by-one error in
parameterCountthat causes large arrays to be parsed as objects with qs@6.14.2.Problem
The
parameterCountfunction counts&characters but returns that count directly. Since the number of parameters equals the number of&characters plus one, this causes an off-by-one error.For example, with
a[0]=1&a[1]=2&...&a[199]=200(200 parameters):&chars)This became problematic with qs@6.14.2 which changed
arrayLimitbehavior to restrict array length instead of max index.Solution
Change
return counttoreturn count + 1inparameterCount.Test Plan
Compatibility
Fixes #715