From 702b5b3c632cb7d7726b0d06d01a37e506e364ce Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Sun, 3 Aug 2025 15:04:54 +0100 Subject: [PATCH] Server: Trying to fix a request parsing error that can potentially crash the error (#12860) --- packages/server/src/utils/requestUtils.ts | 56 +++++++++++++++-------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/packages/server/src/utils/requestUtils.ts b/packages/server/src/utils/requestUtils.ts index 9ac4cae392..1267661de1 100644 --- a/packages/server/src/utils/requestUtils.ts +++ b/packages/server/src/utils/requestUtils.ts @@ -75,29 +75,49 @@ export async function formParse(request: IncomingMessage): Promise { + let promiseCompleted = false; + const form = formidable({ allowEmptyFiles: true, minFileSize: 0, }); - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - form.parse(req, (error: any, fields: Fields, files: Files) => { - if (error) { - error.message = `Could not parse form: ${error.message}`; - reject(error); - return; - } - // Formidable seems to be doing some black magic and once a request - // has been parsed it cannot be parsed again. Doing so will do - // nothing, the code will just end there, or maybe wait - // indefinitely. So we cache the result on success and return it if - // some code somewhere tries again to parse the form. - req.__parsed = { - fields: isFormContentType ? convertFieldsToKeyValue(fields) : fields, - files: convertFieldsToKeyValue(files), - }; - resolve(req.__parsed); - }); + try { + form.on('error', (error) => { + if (promiseCompleted) return; + promiseCompleted = true; + const wrapped = new Error(`Could not parse form (1): ${error.message}`); + reject(wrapped); + }); + + form.parse(req, (error: Error, fields: Fields, files: Files) => { + if (promiseCompleted) return; + promiseCompleted = true; + + if (error) { + error.message = `Could not parse form (2): ${error.message}`; + reject(error); + return; + } + + // Formidable seems to be doing some black magic and once a request + // has been parsed it cannot be parsed again. Doing so will do + // nothing, the code will just end there, or maybe wait + // indefinitely. So we cache the result on success and return it if + // some code somewhere tries again to parse the form. + req.__parsed = { + fields: isFormContentType ? convertFieldsToKeyValue(fields) : fields, + files: convertFieldsToKeyValue(files), + }; + resolve(req.__parsed); + }); + } catch (error) { + if (promiseCompleted) return; + promiseCompleted = true; + + const wrapped = new Error(`Could not parse form (3): ${error.message}`); + reject(wrapped); + } }); }