From cd973a35d8b18671a12062478d39a5bf549fcad8 Mon Sep 17 00:00:00 2001 From: Otto Sichert Date: Wed, 15 Jun 2022 11:23:54 +0200 Subject: [PATCH] Implement manual catching of corrupted ZIP files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Emma Indal Co-authored-by: Anders Näsman Co-authored-by: Raghunandan Balachandran Signed-off-by: Otto Sichert --- .../src/reading/tree/ZipArchiveResponse.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/packages/backend-common/src/reading/tree/ZipArchiveResponse.ts b/packages/backend-common/src/reading/tree/ZipArchiveResponse.ts index e07cedde87..6505ef4d20 100644 --- a/packages/backend-common/src/reading/tree/ZipArchiveResponse.ts +++ b/packages/backend-common/src/reading/tree/ZipArchiveResponse.ts @@ -86,9 +86,22 @@ export class ZipArchiveResponse implements ReadTreeResponse { const files = Array(); - await this.stream - .pipe(unzipper.Parse()) + // Some corrupted ZIP files cause the zlib inflater to hang indefinitely. + // This is a workaround to bail on stuck streams after 3 seconds. + const piped = this.stream.pipe(unzipper.Parse()); + let lastEntryTimeout: NodeJS.Timeout | undefined; + + await piped .on('entry', (entry: Entry) => { + clearTimeout(lastEntryTimeout); + + lastEntryTimeout = setTimeout(() => { + piped.emit( + 'error', + new Error(`Timed out unzipping file ${entry.path}`), + ); + }, 3000); + if (entry.type === 'Directory') { entry.resume(); return; @@ -105,6 +118,8 @@ export class ZipArchiveResponse implements ReadTreeResponse { }) .promise(); + clearTimeout(lastEntryTimeout); + return files; }