From a9a747f5ddfdea8dcbe028d9d31ec01b70a35409 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 25 Nov 2025 09:06:33 -0800 Subject: [PATCH] Avoid double free in steaming fetch --- src/Fetch.js | 8 ++++---- src/lib/libfetch.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Fetch.js b/src/Fetch.js index 75555c6ffada8..bf64bc20f1c93 100644 --- a/src/Fetch.js +++ b/src/Fetch.js @@ -576,7 +576,7 @@ function fetchXHR(fetch, onsuccess, onerror, onprogress, onreadystatechange) { #endif // The data pointer malloc()ed here has the same lifetime as the emscripten_fetch_t structure itself has, and is // freed when emscripten_fetch_close() is called. - ptr = _malloc(ptrLen); + ptr = _realloc({{{ makeGetValue('fetch', C_STRUCTS.emscripten_fetch_t.data, '*') }}}, ptrLen); HEAPU8.set(new Uint8Array(/** @type{Array} */(xhr.response)), ptr); } {{{ makeSetValue('fetch', C_STRUCTS.emscripten_fetch_t.data, 'ptr', '*') }}} @@ -653,8 +653,9 @@ function fetchXHR(fetch, onsuccess, onerror, onprogress, onreadystatechange) { #if ASSERTIONS assert(onprogress, 'When doing a streaming fetch, you should have an onprogress handler registered to receive the chunks!'); #endif - // Allocate byte data in Emscripten heap for the streamed memory block (freed immediately after onprogress call) - ptr = _malloc(ptrLen); + // The data pointer malloc()ed here has the same lifetime as the emscripten_fetch_t structure itself has, and is + // freed when emscripten_fetch_close() is called. + ptr = _realloc({{{ makeGetValue('fetch', C_STRUCTS.emscripten_fetch_t.data }}}, ptrLen); HEAPU8.set(new Uint8Array(/** @type{Array} */(xhr.response)), ptr); } {{{ makeSetValue('fetch', C_STRUCTS.emscripten_fetch_t.data, 'ptr', '*') }}} @@ -668,7 +669,6 @@ function fetchXHR(fetch, onsuccess, onerror, onprogress, onreadystatechange) { {{{ makeSetValue('fetch', C_STRUCTS.emscripten_fetch_t.status, 'status', 'i16') }}} if (xhr.statusText) stringToUTF8(xhr.statusText, fetch + {{{ C_STRUCTS.emscripten_fetch_t.statusText }}}, 64); onprogress(fetch, e); - _free(ptr); }; xhr.onreadystatechange = (e) => { // check if xhr was aborted by user and don't try to call back diff --git a/src/lib/libfetch.js b/src/lib/libfetch.js index 2a7668a4e3e7e..03dba8681e6be 100644 --- a/src/lib/libfetch.js +++ b/src/lib/libfetch.js @@ -29,7 +29,7 @@ var LibraryFetch = { emscripten_start_fetch: startFetch, emscripten_start_fetch__deps: [ 'malloc', - 'free', + 'realloc', '$Fetch', '$fetchXHR', '$callUserCallback',