You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Rendering a layer page that draws an image through an unpromoted tiling pattern dereferences null in CPDF_ImageLoader::Finish #84
Rendering a page of a layer opened with EPDFLayer_OpenLayer crashes when the page paints an image through a tiling pattern the layer hasn't promoted. On native it's a SIGSEGV at address 0x18. In wasm the same read hits linear memory instead of trapping, so it's probably silent corruption, though I haven't confirmed that. The viewer opens every open.fatMem document as a fresh layer (WorkerHost.ts:965), so any such PDF opened in the viewer goes down this path.
Repro, at runtime 1461b0c51 (the C below is the equivalent of the Rust repro I ran; I haven't compiled this exact snippet). The file is examples/react/public/report.pdf from the viewer repo; page index 12 is its first page that uses one of these patterns:
The same page renders fine from a document opened with FPDF_LoadMemDocument. Annotations aren't involved: it crashes with FPDF_ANNOT off.
Cause.GetPattern falls back to the base's page data for an unpromoted pattern (cpdf_docpagedata.cpp:435-438). So the pattern's form, and the images in it, belong to the base document. GetImage deliberately doesn't fall back, for exactly this reason (:490-495), but an image reached through a pattern never goes through it. When the layer page draws the pattern, CPDF_RenderTiling::DrawPatternBitmap renders its form with the layer page's image cache. StartGetCachedBitmap sees the document mismatch and returns false without setting cur_image_cache_entry_ (cpdf_pageimagecache.cpp:177-180). CPDF_ImageLoader::Start reads false as "done" and calls Finish() (cpdf_imageloader.cpp:44), and DetachCurBitmap() reads cur_bitmap_ (offset 0x18) through the null entry.
Fix. I see two options. The first is to stop GetPattern falling back for tiling patterns, keeping the "images are layer-local" rule GetImage's comment states. GetFont needs the same treatment for Type3 fonts whose glyph procedures draw images. That fix costs a little memory, since each layer then parses its own copy of a shared pattern. The second is narrower: have the cross-document branch in StartGetCachedBitmap load the image uncached instead of returning false with no entry. That leaves the fallback alone, but it keeps a path where an image's document and the page's disagree. I'm leaning towards the first, and I'm putting it in my fork with a regression test; I'm happy to open a PR here with it if that's useful.
Activity
bobsingor commentedon Oct 28, 2026
Thanks for the detailed report. This is fixed by #85