From d8165e9f2c4a73176a372d5d84f43c5fd166026b Mon Sep 17 00:00:00 2001 From: Jay Date: Wed, 22 Apr 2026 19:41:11 +0200 Subject: [PATCH] fix: incorrect assumption on test (#10796) * fix: fetch adaptor is not enforcing max body or content length * fix: incomplete fix * fix: improve helper --- lib/adapters/fetch.js | 1 + lib/helpers/estimateDataURLDecodedBytes.js | 30 +++++++++++++++++----- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/lib/adapters/fetch.js b/lib/adapters/fetch.js index c61642b5..7653c491 100644 --- a/lib/adapters/fetch.js +++ b/lib/adapters/fetch.js @@ -312,6 +312,7 @@ const factory = (env) => { if ( supportsResponseStream && + response.body && (onDownloadProgress || hasMaxContentLength || (isStreamResponse && unsubscribe)) ) { const options = {}; diff --git a/lib/helpers/estimateDataURLDecodedBytes.js b/lib/helpers/estimateDataURLDecodedBytes.js index 84e9feb3..bb283ae8 100644 --- a/lib/helpers/estimateDataURLDecodedBytes.js +++ b/lib/helpers/estimateDataURLDecodedBytes.js @@ -73,12 +73,28 @@ export default function estimateDataURLDecodedBytes(url) { return Buffer.byteLength(body, 'utf8'); } - // Browser/worker fallback: use TextEncoder when available, else fall back to - // raw string length as an upper-bound heuristic. Both are safe for a DoS - // guard (over-counting only makes the check stricter for non-ASCII content). - if (typeof TextEncoder === 'function') { - return new TextEncoder().encode(body).byteLength; + // Compute UTF-8 byte length directly from UTF-16 code units without allocating + // a byte buffer (TextEncoder.encode would defeat the DoS guard on large bodies). + // Using body.length here would undercount non-ASCII (e.g. '€' is 1 code unit + // but 3 UTF-8 bytes). + let bytes = 0; + for (let i = 0, len = body.length; i < len; i++) { + const c = body.charCodeAt(i); + if (c < 0x80) { + bytes += 1; + } else if (c < 0x800) { + bytes += 2; + } else if (c >= 0xd800 && c <= 0xdbff && i + 1 < len) { + const next = body.charCodeAt(i + 1); + if (next >= 0xdc00 && next <= 0xdfff) { + bytes += 4; + i++; + } else { + bytes += 3; + } + } else { + bytes += 3; + } } - - return body.length; + return bytes; }