Skip to content

Stream and dictionary object-kind mismatches are recovered as empty content #238

Description

@lin-string

Summary

Stream objects and plain dictionaries are syntactically distinct in PDF, but object-kind mismatches in page structures are downgraded to warnings and hidden by recovery. A dictionary used as page Contents becomes empty content, while a stream used as a page dictionary becomes a synthesized empty page.

Versions tested

Test files

Reproduction

import playa

for path in (
    "Dialect-StreamIsDict.pdf",
    "Dialect-DictIsStream.pdf",
):
    with playa.open(path) as document:
        page = document.pages[0]
        print(path, page.mediabox, list(page.contents), repr(page.extract_text()))

Actual behavior

For Dialect-StreamIsDict.pdf, Playa logs Found non-stream in contents and returns an empty contents sequence without raising an error.

For Dialect-DictIsStream.pdf, Playa logs Missing or invalid page object 4, substitutes an empty 612 by 792 page, and returns empty contents and text without raising an error.

Expected behavior

The missing stream/endstream delimiters in the first file and the unexpected stream wrappers in the second file are PDF syntax errors. The object-kind mismatch should remain observable to callers as a type or syntax error. If recovery is retained, it should not silently replace the malformed objects without an error channel.

Relevant implementation

ContentParser.__init__() catches TypeError from stream_value() and initializes an empty parser buffer; Page.streams catches the same error and skips the object. In the inverse case, Pages._get_pages() catches TypeError from dict_value() and creates a synthetic empty page.

Disclosure

This issue was prepared by an AI coding agent on behalf of @lin-string. The reproduction and results were verified against the current default branch.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions