Skip to content

fix(font): a freed font's subset could be embedded for the next font - #55

Open
serpentblade wants to merge 1 commit into
dskripchenko:mainfrom
serpentblade:fix/subset-cache-object-id
Open

serpentblade wants to merge 1 commit into
dskripchenko:mainfrom
serpentblade:fix/subset-cache-object-id

Conversation

@serpentblade

Copy link
Copy Markdown
Contributor

In a long-running process (Octane, queue workers, batch scripts), a PDF could embed the wrong font. Render with Liberation Sans Regular, let it be freed, then render with Bold: the second PDF embeds Regular.

TtfSubsetter's static cache was keyed by spl_object_id() of the font, and PHP reuses a freed object's id. The two fonts share a glyph order, so the same text produced the same key. Each font now gets a cache id from a counter that is never reused, held in a WeakMap so it goes away with the font. Cache size and eviction are unchanged.

One regression test, failing before the fix. Full suite and phpstan pass on PHP 8.2 and 8.4.

🤖 Generated with Claude Code

TtfSubsetter's static cache was keyed by spl_object_id() of the source
font. PHP reuses a freed object's id, so in a long-running process
(Octane, queue workers, batch scripts) a font loaded after another was
freed could be handed the old font's subset. Liberation Sans Bold got
Regular's bytes: both share a glyph order, so the same text gave the
same key, and the PDF embedded the wrong font.

Each source font now gets a cache id from a counter that is never
reused, held in a WeakMap so it goes away with the font. The cache's
size and eviction are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant