From 10958e6d40e795a8185f9c092276f45f700a4a41 Mon Sep 17 00:00:00 2001 From: Ayoub-Mabrouk Date: Wed, 29 Oct 2025 02:02:59 +0100 Subject: [PATCH] perf(urlencoded): optimize parameter counting for better memory efficiency The previous implementation used ody.split('&') which always processed the entire request body and allocated a full array, regardless of the parameter limit. The new implementation: - Counts '&' characters iteratively without array allocation - Exits immediately when the limit is reached - Handles edge case of empty/null body - Reduces time complexity from O(n) worst-case always to O(min(n, limit)) This particularly improves resilience against malicious requests with thousands of parameters attempting to exhaust server resources --- lib/types/urlencoded.js | 9 +++++++-- test/urlencoded.js | 8 ++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/types/urlencoded.js b/lib/types/urlencoded.js index ae6b2478..28db614c 100644 --- a/lib/types/urlencoded.js +++ b/lib/types/urlencoded.js @@ -131,7 +131,12 @@ function createQueryParser (options) { */ function parameterCount (body, limit) { - var len = body.split('&').length + let count = 0 + for (const char of body) { + if (char === '&') { + if (++count >= limit) return undefined + } + } - return len > limit ? undefined : len - 1 + return count } diff --git a/test/urlencoded.js b/test/urlencoded.js index 49730659..8090dd44 100644 --- a/test/urlencoded.js +++ b/test/urlencoded.js @@ -466,6 +466,14 @@ describe('bodyParser.urlencoded()', function () { }) describe('with parameterLimit option', function () { + it('should handle empty body with parameterLimit', function (done) { + request(createServer({ parameterLimit: 10 })) + .post('/') + .set('Content-Type', 'application/x-www-form-urlencoded') + .send('') + .expect(200, '{}', done) + }) + describe('with extended: false', function () { it('should reject 0', function () { assert.throws(createServer.bind(null, { extended: false, parameterLimit: 0 }),