Skip to content

Fix Font::getDetails() TypeError when Encoding is indirect reference to PDFObject#823

Open
kernie wants to merge 1 commit into
smalot:masterfrom
kernie:fix/822-font-getdetails-encoding-as-pdfobject
Open

Fix Font::getDetails() TypeError when Encoding is indirect reference to PDFObject#823
kernie wants to merge 1 commit into
smalot:masterfrom
kernie:fix/822-font-getdetails-encoding-as-pdfobject

Conversation

@kernie

@kernie kernie commented Jun 4, 2026

Copy link
Copy Markdown

Type of pull request

  • Bug fix (involves code and configuration changes)
  • New feature (involves code and configuration changes)
  • Documentation update
  • Something else

About

fixes #822

Font::getDetails() threw "PDFObject could not be converted to string" when a font's /Encoding entry was an indirect reference resolving to a plain PDFObject (encoding dictionary without /Type /Encoding). This is a valid PDF structure per spec Table 5.11.

Root cause: Font::getDetails() applied an unconditional (string) cast to the result of $this->get('Encoding'). Header::resolveXRef() can return a PDFObject (which has no __toString()), causing a TypeError in PHP 8+.

Fix: Check the type before casting:

  • PDFObject (covers both Encoding subclass and plain encoding dictionaries): extract BaseEncoding name; fall back to 'Ansi' if absent — consistent with Encoding::getDetails()['BaseEncoding'].
  • Element (direct name like /WinAnsiEncoding): cast as before.
  • null (no entry): return 'Ansi' as before.

Changes:

  • src/Smalot/PdfParser/Font.php — fix in getDetails()
  • tests/PHPUnit/Unit/FontTest.php — 5 unit tests covering all branches
  • tests/PHPUnit/Integration/FontTest.php — integration test with sample PDF
  • samples/bugs/EncodingAsIndirectPDFObject.pdf — minimal reproducer (720 B)

AI disclosure
This PR was developed with Claude Code assistance. All code has been reviewed as best I can. I tested the code in my local installation.

…malot#822)

When a font's /Encoding entry is an indirect object reference that resolves
to a plain PDFObject (encoding dictionary without /Type /Encoding), the
previous unconditional (string) cast failed because PDFObject has no
__toString() method.

Fix: check the type before casting —
- PDFObject (covers Encoding subclass and plain dicts): extract BaseEncoding
  name, fall back to 'Ansi' consistent with Encoding::getDetails()
- Element (direct name like /WinAnsiEncoding): cast as before
- null (no entry): return 'Ansi' as before

Adds 5 unit tests covering all branches and one integration test with a
minimal reproducer PDF (samples/bugs/EncodingAsIndirectPDFObject.pdf).

fixes smalot#822
@k00ni

k00ni commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Thank you @kernie! I hope there is a German holiday soon, so I have some time to get on this 😅 Its looks very polished already at first glance.

@k00ni k00ni added the fix label Jun 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Font::getDetails() throws TypeError when Encoding is indirect reference to PDFObject

2 participants