Files
rengine/shared
Yogesh OjhaandClaude Opus 5 927b95296c fix(reports): images are upload-only, and a small one can no longer exhaust memory
Audited every path an image can reach the renderer by, on the principle that
uploads are the only source. Four of the five were already closed, and the one
that mattered most turned out to be closed for a reason worth recording: an SVG
logo cannot beacon or read a file, because references made from inside the SVG
go through the same fetcher, and WeasyPrint's SVG parser does not resolve XML
entities. An <image href> pointing at a listener got zero hits; an XXE entity
leaked nothing. So SVG stays. Rasterising a logo to avoid a risk that is already
closed would cost real print quality for nothing.

The gap was not a URL at all. WeasyPrint passes a PNG stream straight into the
PDF, so the output stays small, but it still decodes the image: inside the 500 KB
logo limit, a 182 KB file decodes to 64M pixels and cost a measured +594 MB of
RSS, and Pillow's 89M default only warns below twice the limit. Across eight
workers that is several gigabytes from a handful of small uploads. The render now
caps decoded pixels, which takes that same payload to +0 MB, and a dropped image
is surfaced as a report warning instead of vanishing.

Two things this exposed about the previous commit. The fetcher was built on
default_url_fetcher, deprecated in WeasyPrint 69; it is now a URLFetcher subclass
pinned to the data and file protocols. And the first attempt at the pixel cap
silently missed, because the edit was written against a function ruff had already
reformatted: the guard existed, nothing called it, and the probe reported success
by rendering the bomb. Measuring the test harness separately from the renderer is
what caught it.

cover_image was a validated field nothing rendered. It is wired now, uploaded and
embedded like the logo, so it is no longer dead configuration.

Verified after the rewrite: 11/11 on the fetcher matrix, a 124-page report with
the uploaded typeface still embedded, and screenshots still embedding.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017f2Mf2HGwFaTRnui4UxpRd
2026-09-06 13:07:53 +05:30
..
2026-01-26 15:02:53 +05:30
2026-09-04 18:57:42 +05:30