Skip to content

fix(urlencoded): prevent 32-bit integer overflow in parameterLimit - #785

Open
helmipradita wants to merge 1 commit into
expressjs:masterfrom
helmipradita:fix/parameter-limit-integer-overflow
Open

helmipradita wants to merge 1 commit into
expressjs:masterfrom
helmipradita:fix/parameter-limit-integer-overflow

Conversation

@helmipradita

Copy link
Copy Markdown

Problem

In lib/types/urlencoded.js, parameterLimit was coerced to an integer using bitwise OR:

if (isFinite(parameterLimit)) {
  parameterLimit = parameterLimit | 0
}

Because bitwise operators in JavaScript convert operands to 32-bit signed integers (ToInt32), configuring parameterLimit to a value greater than or equal to $2^{31}$ (such as 3000000000) caused it to overflow into a negative integer (-1294967296).

When parsing any incoming URL-encoded payload (even a valid single-parameter request like user=tobi), parameterCount checked count > limit (1 > -1294967296), immediately returning undefined and rejecting legitimate requests with HTTP 413 too many parameters.

Solution

Replace parameterLimit | 0 with Math.trunc(parameterLimit). This preserves floating-point truncation (e.g. 10.5 becomes 10) while correctly handling numbers up to Number.MAX_SAFE_INTEGER without 32-bit overflow.

Validation

  • Added unit tests for both extended: false and extended: true in test/urlencoded.js asserting that parameterLimit: 3000000000 succeeds for incoming payloads.
  • Verified all 279 tests pass with npm test.
  • Verified formatting and linting pass with npm run lint.

Using bitwise `parameterLimit | 0` truncated the limit to a 32-bit signed
integer (ToInt32). When `parameterLimit` was set to a value >= 2^31 (e.g. 3000000000),
it wrapped to a negative number, causing `parameterCount` to immediately treat
any request as exceeding the limit and return 413.

Use `Math.trunc(parameterLimit)` to truncate floating-point numbers without
overflowing large integers within JavaScript safe integer range.
@krzysdz

krzysdz commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

Setting parameterLimit to anything that triggers this bug opens your app to DoS. At 10k parameters, it can take about 1 second to parse an array and the time complexity is quadratic (ljharb/qs#544).

@helmipradita

Copy link
Copy Markdown
Author

Agreed @krzysdz! The primary goal of this PR is to prevent the 32-bit integer overflow where setting parameterLimit above 2^31 - 1 wraps the limit to a negative number and breaks normal requests with an immediate 413 error.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants