Skip to content

SEC: Prevent infinite loop from circular xref /Prev references#3655

Merged
stefan6419846 merged 2 commits intopy-pdf:mainfrom
rampageservices:fix/circular-xref-infinite-loop
Feb 22, 2026
Merged

SEC: Prevent infinite loop from circular xref /Prev references#3655
stefan6419846 merged 2 commits intopy-pdf:mainfrom
rampageservices:fix/circular-xref-infinite-loop

Conversation

@rampageservices
Copy link
Contributor

Summary

Fixes #3654

A crafted PDF with circular /Prev references in its cross-reference table causes _read_xref_tables_and_trailers() to loop indefinitely, hanging the process. This is a denial-of-service vulnerability (CWE-835) for any application that parses untrusted PDFs.

Root Cause

In _reader.py, the while startxref is not None loop at line ~874 follows /Prev pointers to walk the xref chain but has no guard against circular references. If /Prev points back to an already-visited offset, the loop never terminates.

Fix

Added a visited_xref_offsets set that tracks every xref offset before processing. If a previously-seen offset is encountered, the loop logs a warning and breaks — consistent with the existing circular-reference guard pattern used elsewhere in pypdf (e.g., outlines traversal after CVE-2026-24688).

Security Note

This is the same vulnerability class as CVE-2026-24688 and GHSA-hm9v-vj3r-r55m. A GitHub Security Advisory / CVE assignment may be appropriate.

Test

Discovered in production processing LCSC datasheets. The affected PDF triggers "Overwriting cache for X Y" log spam in an infinite loop during xref parsing.

Malformed PDFs can contain circular /Prev references in the xref
chain (e.g., xref A -> /Prev -> xref B -> /Prev -> xref A).
This causes _read_xref_tables_and_trailers() to loop forever,
spamming "Overwriting cache for N M" warnings on every iteration
as the same objects are re-parsed and re-cached indefinitely.

Fix: Track visited xref offsets in a set. If a startxref value
has already been visited, log a warning and break the loop.

Closes py-pdf#3654
@rampageservices rampageservices force-pushed the fix/circular-xref-infinite-loop branch from 3a379b9 to 0fbd959 Compare February 21, 2026 15:24
@rampageservices rampageservices changed the title Fix infinite loop on circular xref /Prev references BUG: Prevent infinite loop from circular xref /Prev references Feb 21, 2026
@codecov
Copy link

codecov bot commented Feb 21, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.35%. Comparing base (4670513) to head (8beff19).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3655   +/-   ##
=======================================
  Coverage   97.35%   97.35%           
=======================================
  Files          55       55           
  Lines        9916     9921    +5     
  Branches     1814     1815    +1     
=======================================
+ Hits         9654     9659    +5     
  Misses        152      152           
  Partials      110      110           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Add a dedicated test that constructs a synthetic PDF with a self-referencing
/Prev trailer entry to verify the circular xref chain detection works
correctly and doesn't hang.
@rampageservices rampageservices force-pushed the fix/circular-xref-infinite-loop branch from eaa8d91 to 8beff19 Compare February 21, 2026 17:27
@stefan6419846 stefan6419846 changed the title BUG: Prevent infinite loop from circular xref /Prev references SEC: Prevent infinite loop from circular xref /Prev references Feb 22, 2026
@stefan6419846 stefan6419846 merged commit f0a462d into py-pdf:main Feb 22, 2026
19 checks passed
stefan6419846 added a commit that referenced this pull request Feb 22, 2026
## What's new

### Security (SEC)
- Prevent infinite loop from circular xref /Prev references (#3655) by @rampageservices

### Bug Fixes (BUG)
- Fix wrong LUT size error (#3651) by @stefan6419846
- Fix handling of page boxes defined on `/Pages` (#3650) by @stefan6419846

[Full Changelog](6.7.1...6.7.2)
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.

BUG: Infinite loop from circular /Prev xref references

2 participants