From dc8445fbafb22254e8716217afc450fe1f13f17d Mon Sep 17 00:00:00 2001 From: PrinsFrank <25006490+PrinsFrank@users.noreply.github.com> Date: Mon, 15 Jun 2026 23:18:34 +0200 Subject: [PATCH] Gracefully handle exceptions in recovered cross reference sources --- .../CrossReference/Source/CrossReferenceSource.php | 2 ++ .../Source/RecoveredCrossReferenceSource.php | 8 +++++++- .../Source/Section/CrossReferenceSection.php | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Document/CrossReference/Source/CrossReferenceSource.php b/src/Document/CrossReference/Source/CrossReferenceSource.php index 8a543de..8aac1a8 100644 --- a/src/Document/CrossReference/Source/CrossReferenceSource.php +++ b/src/Document/CrossReference/Source/CrossReferenceSource.php @@ -14,6 +14,7 @@ use PrinsFrank\PdfParser\Document\Dictionary\DictionaryValue\Reference\ReferenceValue; use PrinsFrank\PdfParser\Document\Document; use PrinsFrank\PdfParser\Exception\ParseFailureException; +use PrinsFrank\PdfParser\Exception\RuntimeException; use PrinsFrank\PdfParser\Stream\Stream; /** Can be both from a crossReferenceTable or a crossReferenceStream */ @@ -28,6 +29,7 @@ public function __construct( $this->crossReferenceSections = $crossReferenceSections; } + /** @throws RuntimeException */ public function getCrossReferenceEntry(int $objNumber, Document $document): CrossReferenceEntryInUseObject|CrossReferenceEntryCompressed|null { foreach ($this->crossReferenceSections as $crossReferenceSection) { $crossReferenceEntry = $crossReferenceSection->getCrossReferenceEntry($objNumber); diff --git a/src/Document/CrossReference/Source/RecoveredCrossReferenceSource.php b/src/Document/CrossReference/Source/RecoveredCrossReferenceSource.php index 30a3efb..0524a3c 100644 --- a/src/Document/CrossReference/Source/RecoveredCrossReferenceSource.php +++ b/src/Document/CrossReference/Source/RecoveredCrossReferenceSource.php @@ -7,6 +7,7 @@ use PrinsFrank\PdfParser\Document\CrossReference\Source\Section\SubSection\Entry\CrossReferenceEntryCompressed; use PrinsFrank\PdfParser\Document\CrossReference\Source\Section\SubSection\Entry\CrossReferenceEntryInUseObject; use PrinsFrank\PdfParser\Document\Document; +use Throwable; class RecoveredCrossReferenceSource extends CrossReferenceSource { /** @@ -23,7 +24,12 @@ public function __construct( #[Override] public function getCrossReferenceEntry(int $objNumber, Document $document): CrossReferenceEntryInUseObject|CrossReferenceEntryCompressed|null { - $crossReferenceEntry = parent::getCrossReferenceEntry($objNumber, $document); + try { + $crossReferenceEntry = parent::getCrossReferenceEntry($objNumber, $document); + } catch (Throwable) { + $crossReferenceEntry = null; + } + if ($crossReferenceEntry instanceof CrossReferenceEntryInUseObject && $document->stream->read($crossReferenceEntry->byteOffsetInDecodedStream, strlen($expectedStartObjMarker = sprintf('%d %d obj', $objNumber, $crossReferenceEntry->generationNumber))) === $expectedStartObjMarker) { return $crossReferenceEntry; diff --git a/src/Document/CrossReference/Source/Section/CrossReferenceSection.php b/src/Document/CrossReference/Source/Section/CrossReferenceSection.php index 2e6efc2..120a19b 100644 --- a/src/Document/CrossReference/Source/Section/CrossReferenceSection.php +++ b/src/Document/CrossReference/Source/Section/CrossReferenceSection.php @@ -6,6 +6,7 @@ use PrinsFrank\PdfParser\Document\CrossReference\Source\Section\SubSection\Entry\CrossReferenceEntryCompressed; use PrinsFrank\PdfParser\Document\CrossReference\Source\Section\SubSection\Entry\CrossReferenceEntryInUseObject; use PrinsFrank\PdfParser\Document\Dictionary\Dictionary; +use PrinsFrank\PdfParser\Exception\RuntimeException; use PrinsFrank\PdfParser\Stream\Stream; /** There are multiple crossReference sections if there are incremental updates. See 7.5.6 */ @@ -21,6 +22,7 @@ public function __construct( $this->crossReferenceSubSections = $crossReferenceSubSections; } + /** @throws RuntimeException */ public function getCrossReferenceEntry(int $objNumber): CrossReferenceEntryInUseObject|CrossReferenceEntryCompressed|null { foreach ($this->crossReferenceSubSections as $crossReferenceSubSection) { if ($crossReferenceSubSection->containsObject($objNumber)) {