From b5ed98826763773e416f45ec8e9b1bfddc142eca Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Tue, 13 Jan 2026 18:39:08 +0100 Subject: [PATCH] Don't use contents stream which have an image format The original bug has been filled in mupdf bug tracker: https://bugs.ghostscript.com/show_bug.cgi?id=709033 The attached pdf can be open in Chrome but not in Acrobat. --- src/core/base_stream.js | 4 ++++ src/core/ccitt_stream.js | 4 ++++ src/core/decode_stream.js | 2 +- src/core/document.js | 2 +- src/core/jbig2_stream.js | 4 ++++ src/core/jpeg_stream.js | 4 ++++ src/core/jpx_stream.js | 4 ++++ test/pdfs/.gitignore | 1 + test/pdfs/bomb_giant.pdf | Bin 0 -> 123242 bytes test/test_manifest.json | 7 +++++++ 10 files changed, 30 insertions(+), 2 deletions(-) create mode 100755 test/pdfs/bomb_giant.pdf diff --git a/src/core/base_stream.js b/src/core/base_stream.js index a5a0eb1b556f7..bf252b24e7297 100644 --- a/src/core/base_stream.js +++ b/src/core/base_stream.js @@ -68,6 +68,10 @@ class BaseStream { return false; } + get isImageStream() { + return false; + } + get canAsyncDecodeImageFromBuffer() { return false; } diff --git a/src/core/ccitt_stream.js b/src/core/ccitt_stream.js index 2bb80f3afa4f2..ca173f460b5c0 100644 --- a/src/core/ccitt_stream.js +++ b/src/core/ccitt_stream.js @@ -55,6 +55,10 @@ class CCITTFaxStream extends DecodeStream { this.buffer[this.bufferLength++] = c; } } + + get isImageStream() { + return true; + } } export { CCITTFaxStream }; diff --git a/src/core/decode_stream.js b/src/core/decode_stream.js index b541ed8983077..c76078f111cce 100644 --- a/src/core/decode_stream.js +++ b/src/core/decode_stream.js @@ -148,7 +148,7 @@ class DecodeStream extends BaseStream { class StreamsSequenceStream extends DecodeStream { constructor(streams, onError = null) { - streams = streams.filter(s => s instanceof BaseStream); + streams = streams.filter(s => s instanceof BaseStream && !s.isImageStream); let maybeLength = 0; for (const stream of streams) { diff --git a/src/core/document.js b/src/core/document.js index f624458cb24ca..a33d20385c09c 100644 --- a/src/core/document.js +++ b/src/core/document.js @@ -270,7 +270,7 @@ class Page { async getContentStream() { const content = await this.pdfManager.ensure(this, "content"); - if (content instanceof BaseStream) { + if (content instanceof BaseStream && !content.isImageStream) { return content; } if (Array.isArray(content)) { diff --git a/src/core/jbig2_stream.js b/src/core/jbig2_stream.js index 0fdda06ae1a93..c62c3580ce1e8 100644 --- a/src/core/jbig2_stream.js +++ b/src/core/jbig2_stream.js @@ -52,6 +52,10 @@ class Jbig2Stream extends DecodeStream { return true; } + get isImageStream() { + return true; + } + async decodeImage(bytes, _decoderOptions) { if (this.eof) { return this.buffer; diff --git a/src/core/jpeg_stream.js b/src/core/jpeg_stream.js index 4af24eeb8e733..75511f7087853 100644 --- a/src/core/jpeg_stream.js +++ b/src/core/jpeg_stream.js @@ -194,6 +194,10 @@ class JpegStream extends DecodeStream { decoder?.close(); } } + + get isImageStream() { + return true; + } } export { JpegStream }; diff --git a/src/core/jpx_stream.js b/src/core/jpx_stream.js index e454d58bd9754..54938eb745d41 100644 --- a/src/core/jpx_stream.js +++ b/src/core/jpx_stream.js @@ -64,6 +64,10 @@ class JpxStream extends DecodeStream { get canAsyncDecodeImageFromBuffer() { return this.stream.isAsync; } + + get isImageStream() { + return true; + } } export { JpxStream }; diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 4a7a9a6e9b2d7..7b1a154a0ef1c 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -866,3 +866,4 @@ !bitmap-trailing-7fff-stripped-harder.pdf !bitmap-trailing-7fff-stripped.pdf !bitmap.pdf +!bomb_giant.pdf diff --git a/test/pdfs/bomb_giant.pdf b/test/pdfs/bomb_giant.pdf new file mode 100755 index 0000000000000000000000000000000000000000..bbc7a43af92adf0a77e698948014e3871e9e595d GIT binary patch literal 123242 zcmeIv&u$Y(7y$4!-1Z1BFc%O#(B1XF#FA^NZb%vm1%=#D4^BKJj)Gm;OGSI(#%sU> zXZLaOV>c~A9u`Mu>2Mgb!@vKGA^T-gPRl*akAPOSg`w%{@^`)xK|h1Z=r{g3LD#k+YKife`S&h5hbnq{m~ zFYn2o$LVY`Uc3*l^D4hzw8Pe*-JCZstF-EdUVTI8H}h6AZ`X5`a}ZaHcgy3d>H62~ zE~-{bFHH~`fW!|P4?>DQQ1(`AVtW=lU2Oj`8A&Z70cQ2v}sd{{M9gmyO^z6rfNY~^`4oQ6kx`#=AF7@m&z_u66n z;`#W8aClZ7^|;e)*Cj<$@~Ft`@&57^ehS5pMSpJ`;^g?Wsd;i(f1s<|u0B<5bfc+m zzSZwkt<28LxC~iy@lHHmOyjj?lWOEitD5g8t&g9Zr;b&l4p#HSdhzMr&D|uqyZN%Y zvtF++TAL642oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkL{yA`-d<9xa*mvQp8UM-H!(yfq(`aK+m z>{*x~q#AkB zs^*MF&{mQO-}009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RrE#z(pG8(^a{QlehJ1adeixU&c3S9tLUt{|NnFuhR=}!q?a!G`nH`HP+j{6)TF~ ztysHX+=_KN{adl__RZRE(P_7D