From 95a3ad9804a81bfca584530ce71b990411f611f8 Mon Sep 17 00:00:00 2001 From: MK Date: Thu, 21 May 2026 15:43:20 +0800 Subject: [PATCH 1/2] fix(koa): handle Content-Length overflow and NaN Add explicit radix 10 to Number.parseInt and return undefined for non-numeric Content-Length values, matching the documented `number | undefined` contract. Add regression tests for >2GB, 10GB, decimal, non-numeric, and empty-string headers. Ref: https://github.com/koajs/koa/pull/1961 --- packages/koa/src/request.ts | 3 +- packages/koa/test/request/length.test.ts | 36 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/packages/koa/src/request.ts b/packages/koa/src/request.ts index ffe0761dca..84b208532e 100644 --- a/packages/koa/src/request.ts +++ b/packages/koa/src/request.ts @@ -328,7 +328,8 @@ export class Request { if (len === '') { return; } - return Number.parseInt(len); + const parsed = Number.parseInt(len, 10); + return Number.isNaN(parsed) ? undefined : parsed; } /** diff --git a/packages/koa/test/request/length.test.ts b/packages/koa/test/request/length.test.ts index 64a8e1457d..2cbb4bc5ef 100644 --- a/packages/koa/test/request/length.test.ts +++ b/packages/koa/test/request/length.test.ts @@ -15,4 +15,40 @@ describe('ctx.length', () => { const req = request(); assert.strictEqual(req.length, undefined); }); + + it('should handle zero content-length', () => { + const req = request(); + req.header['content-length'] = '0'; + assert.strictEqual(req.length, 0); + }); + + it('should handle Content-Length > 2GB (2147483648)', () => { + const req = request(); + req.header['content-length'] = '2147483648'; + assert.strictEqual(req.length, 2147483648); + }); + + it('should handle very large Content-Length (10GB)', () => { + const req = request(); + req.header['content-length'] = '10000000000'; + assert.strictEqual(req.length, 10000000000); + }); + + it('should handle floating-point-like strings (truncate decimal)', () => { + const req = request(); + req.header['content-length'] = '10.5'; + assert.strictEqual(req.length, 10); + }); + + it('should return undefined for non-numeric strings', () => { + const req = request(); + req.header['content-length'] = 'invalid'; + assert.strictEqual(req.length, undefined); + }); + + it('should return undefined for empty string', () => { + const req = request(); + req.header['content-length'] = ''; + assert.strictEqual(req.length, undefined); + }); }); From 051e6cbc819606745bb472e19215a8f49b370dcb Mon Sep 17 00:00:00 2001 From: MK Date: Thu, 21 May 2026 15:55:22 +0800 Subject: [PATCH 2/2] fix(koa): add radix to Response.length parseInt Mirror the Request.length fix on the Response sibling getter to keep the fork aligned with upstream koa. Preserves the existing `|| 0` fallback so the behavior for non-numeric headers is unchanged. Ref: https://github.com/koajs/koa/pull/1961 --- packages/koa/src/response.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/koa/src/response.ts b/packages/koa/src/response.ts index 4115953f34..6a25c79e78 100644 --- a/packages/koa/src/response.ts +++ b/packages/koa/src/response.ts @@ -189,7 +189,7 @@ export class Response { */ get length(): number | undefined { if (this.has('Content-Length')) { - return Number.parseInt(this.get('Content-Length')) || 0; + return Number.parseInt(this.get('Content-Length'), 10) || 0; } const body = this.body;