From f195d275b29f28b904d784255050216163696340 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Thu, 23 Apr 2026 22:41:50 -0300 Subject: [PATCH 01/47] fix: deduplicate duplicate kids references in getPages Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/Smalot/PdfParser/Document.php | 33 ++++++++++++++++++++-- tests/PHPUnit/Integration/DocumentTest.php | 28 ++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/Smalot/PdfParser/Document.php b/src/Smalot/PdfParser/Document.php index 1fad8b1ba..80d6f2197 100644 --- a/src/Smalot/PdfParser/Document.php +++ b/src/Smalot/PdfParser/Document.php @@ -401,7 +401,7 @@ public function getPages() /** @var Pages $object */ $object = $catalogue->get('Pages'); if (method_exists($object, 'getPages')) { - return $object->getPages(true); + return $this->uniquePages($object->getPages(true)); } } @@ -415,19 +415,46 @@ public function getPages() $pages = array_merge($pages, $object->getPages(true)); } - return $pages; + return $this->uniquePages($pages); } if ($this->hasObjectsByType('Page')) { // Search for 'page' (unordered pages). $pages = $this->getObjectsByType('Page'); - return array_values($pages); + return $this->uniquePages(array_values($pages)); } throw new MissingCatalogException('Missing catalog.'); } + /** + * @param array $pages + * + * @return array + */ + protected function uniquePages(array $pages): array + { + $unique = []; + $seen = []; + + foreach ($pages as $page) { + if (!\is_object($page)) { + continue; + } + + $id = spl_object_id($page); + if (isset($seen[$id])) { + continue; + } + + $seen[$id] = true; + $unique[] = $page; + } + + return $unique; + } + public function getText(?int $pageLimit = null): string { $texts = []; diff --git a/tests/PHPUnit/Integration/DocumentTest.php b/tests/PHPUnit/Integration/DocumentTest.php index 346ba6331..2a28b96bb 100644 --- a/tests/PHPUnit/Integration/DocumentTest.php +++ b/tests/PHPUnit/Integration/DocumentTest.php @@ -233,6 +233,34 @@ public function testGetPagesMissingCatalog(): void $document->getPages(); } + public function testGetPagesDeduplicatesDuplicateKidsReferences(): void + { + $document = $this->getDocumentInstance(); + + $content = '<>'; + $header = Header::parse($content, $document); + $page = $this->getPageInstance($document, $header); + + $content = '<>'; + $header = Header::parse($content, $document); + $pagesNode = $this->getPagesInstance($document, $header); + + $content = '<>'; + $header = Header::parse($content, $document); + $catalog = $this->getPDFObjectInstance($document, $header); + + $document->setObjects([ + '10_0' => $page, + '20_0' => $pagesNode, + '30_0' => $catalog, + ]); + + $pages = $document->getPages(); + + $this->assertCount(1, $pages); + $this->assertSame($page, $pages[0]); + } + /** * @see https://github.com/smalot/pdfparser/issues/721 */ From a6175406834f82c224fb6c2d2c66a847de416234 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Thu, 23 Apr 2026 22:45:34 -0300 Subject: [PATCH 02/47] test: add duplicate-kids PDF fixture regression Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- samples/bugs/PullRequestDuplicateKids.pdf | Bin 0 -> 437 bytes .../Integration/DocumentIssueFocusTest.php | 9 +++++++++ 2 files changed, 9 insertions(+) create mode 100644 samples/bugs/PullRequestDuplicateKids.pdf diff --git a/samples/bugs/PullRequestDuplicateKids.pdf b/samples/bugs/PullRequestDuplicateKids.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e69a85cc51ff6192dda85df6f1f783f82bf59f90 GIT binary patch literal 437 zcmZXRO-}1zoAdB&7Ld{GCLgiw?bIJ&sfgE#C+BmCum}~~$Ofa|hc%T+_1E=@ zPX>N{9?*5^jRYzqrhs-Q@@tOUTkfMF=GQ87_=MUTX2JBuFtemQ(N;m p;j}h`mV)iK7`W@t{TG4(*?6BIe+PFvCL0phq^~Mb6tkzf_y&#taGU@D literal 0 HcmV?d00001 diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 7c7fe7e68..659583cad 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -111,4 +111,13 @@ public function testPDFDocEncodingDecode(): void $testSubject = '•†‡…—–ƒ⁄‹›−‰„“”‘’‚™ŁŒŠŸŽıłœšž'; self::assertStringContainsString($testSubject, $details['Subject']); } + + public function testGetPagesDeduplicatesDuplicateKidsFixture(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequestDuplicateKids.pdf'); + + $pages = $document->getPages(); + + self::assertCount(1, $pages); + } } From ace7d51c2ce3eb0baa279c856d591ebda3b3ebdf Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Thu, 23 Apr 2026 22:47:24 -0300 Subject: [PATCH 03/47] test: add @see link for duplicate-kids regression Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- tests/PHPUnit/Integration/DocumentIssueFocusTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 659583cad..3023a0280 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -112,6 +112,9 @@ public function testPDFDocEncodingDecode(): void self::assertStringContainsString($testSubject, $details['Subject']); } + /** + * @see https://github.com/smalot/pdfparser/pull/795 + */ public function testGetPagesDeduplicatesDuplicateKidsFixture(): void { $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequestDuplicateKids.pdf'); From bbbd1d35c0d54268ccaed2c923f38a7c68a363df Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Thu, 23 Apr 2026 22:51:24 -0300 Subject: [PATCH 04/47] fix: support php 7.1 in page deduplication Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/Smalot/PdfParser/Document.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Smalot/PdfParser/Document.php b/src/Smalot/PdfParser/Document.php index 80d6f2197..bcd1716bd 100644 --- a/src/Smalot/PdfParser/Document.php +++ b/src/Smalot/PdfParser/Document.php @@ -443,7 +443,9 @@ protected function uniquePages(array $pages): array continue; } - $id = spl_object_id($page); + $id = \function_exists('spl_object_id') + ? (string) \spl_object_id($page) + : \spl_object_hash($page); if (isset($seen[$id])) { continue; } From e5eae4eb9de6f994ddae34552f5071d588ac6f49 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Thu, 23 Apr 2026 23:55:34 -0300 Subject: [PATCH 05/47] fix: preserve absolute xref offsets with pre-header bytes Some PDFs include bytes before the %PDF- header while still using absolute xref offsets from the beginning of the file. The parser trimmed data before %PDF-, which shifted offsets and caused xref lookup failures. This manifested as an Invalid object reference error in the veraPDF corpus header case. Changes: - Keep original byte layout in RawDataParser::parseData - Add stricter trailer key matching for /Size /Root /Encrypt /Info /Prev - Add defensive handling in xref stream resolution when startxref is near, but not exactly at, the xref stream object - Add regression fixture and integration test Regression fixture: - samples/bugs/PullRequestInvalidObjectReference.pdf Test: - DocumentIssueFocusTest::testParseFileWithCompressedObjRefInXrefStream Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .../PullRequestInvalidObjectReference.pdf | Bin 0 -> 9393 bytes .../PdfParser/RawData/RawDataParser.php | 44 ++++++++++++++---- .../Integration/DocumentIssueFocusTest.php | 7 +++ 3 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 samples/bugs/PullRequestInvalidObjectReference.pdf diff --git a/samples/bugs/PullRequestInvalidObjectReference.pdf b/samples/bugs/PullRequestInvalidObjectReference.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9d15f2474e107c6029772e2ef2107e7d59458dac GIT binary patch literal 9393 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 literal 0 HcmV?d00001 diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index ec8d01e53..025d651a7 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -198,16 +198,16 @@ protected function decodeXref(string $pdfData, int $startxref, array $xref = [], // get only the last updated version $xref['trailer'] = []; // parse trailer_data - if (preg_match('/Size[\s]+([0-9]+)/i', $trailer_data, $matches) > 0) { + if (preg_match('/\/Size[\s]+([0-9]+)/i', $trailer_data, $matches) > 0) { $xref['trailer']['size'] = (int) $matches[1]; } - if (preg_match('/Root[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { + if (preg_match('/\/Root[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { $xref['trailer']['root'] = (int) $matches[1].'_'.(int) $matches[2]; } - if (preg_match('/Encrypt[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { + if (preg_match('/\/Encrypt[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { $xref['trailer']['encrypt'] = (int) $matches[1].'_'.(int) $matches[2]; } - if (preg_match('/Info[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { + if (preg_match('/\/Info[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { $xref['trailer']['info'] = (int) $matches[1].'_'.(int) $matches[2]; } if (preg_match('/ID[\s]*[\[][\s]*[<]([^>]*)[>][\s]*[<]([^>]*)[>]/i', $trailer_data, $matches) > 0) { @@ -216,7 +216,7 @@ protected function decodeXref(string $pdfData, int $startxref, array $xref = [], $xref['trailer']['id'][1] = $matches[2]; } } - if (preg_match('/Prev[\s]+([0-9]+)/i', $trailer_data, $matches) > 0) { + if (preg_match('/\/Prev[\s]+([0-9]+)/i', $trailer_data, $matches) > 0) { $offset = (int) $matches[1]; if (0 != $offset) { // get previous xref @@ -246,7 +246,28 @@ protected function decodeXrefStream(string $pdfData, int $startxref, array $xref { // try to read Cross-Reference Stream $xrefobj = $this->getRawObject($pdfData, $startxref); - $xrefcrs = $this->getIndirectObject($pdfData, $xref, $xrefobj[1], $startxref, true); + $xrefObjRef = isset($xrefobj[1]) && \is_string($xrefobj[1]) ? $xrefobj[1] : ''; + $xrefObjOffset = $startxref; + + // Some malformed files have a startxref that points near the xref stream object. + // Try to recover a nearby valid object header instead of failing hard. + if (0 === preg_match('/^[0-9]+_[0-9]+$/', $xrefObjRef)) { + if ( + preg_match('/([0-9]+)[\x20]+([0-9]+)[\x20]+obj/i', $pdfData, $matches, \PREG_OFFSET_CAPTURE, $startxref) > 0 + && ($matches[0][1] - $startxref) <= 64 + ) { + $xrefObjRef = (int) $matches[1][0].'_'.(int) $matches[2][0]; + $xrefObjOffset = $matches[0][1]; + } + } + + if (0 === preg_match('/^[0-9]+_[0-9]+$/', $xrefObjRef)) { + // Could not resolve a valid xref stream object reference at this offset. + // Keep already collected xref data instead of aborting parsing. + return $xref; + } + + $xrefcrs = $this->getIndirectObject($pdfData, $xref, $xrefObjRef, $xrefObjOffset, true); if (!isset($xref['trailer']) || empty($xref['trailer'])) { // get only the last updated version $xref['trailer'] = []; @@ -607,11 +628,15 @@ protected function getObjectVal(string $pdfData, $xref, array $obj): array if (isset($this->objects[$obj[1]])) { // this object has been already parsed return $this->objects[$obj[1]]; - } elseif (isset($xref[$obj[1]])) { + } elseif (isset($xref[$obj[1]]) && $xref[$obj[1]] > 0) { // parse new object $this->objects[$obj[1]] = $this->getIndirectObject($pdfData, $xref, $obj[1], $xref[$obj[1]], false); return $this->objects[$obj[1]]; + } elseif (isset($xref[$obj[1]]) && $xref[$obj[1]] <= 0) { + // Compressed object references are resolved later from object streams in Parser::parseObject(). + // At raw parsing stage, treat unresolved references as null instead of throwing. + return ['null', 'null', 0]; } } @@ -964,8 +989,9 @@ public function parseData(string $data): array throw new MissingPdfHeaderException('Invalid PDF data: Missing `%PDF-` header.'); } - // get PDF content string - $pdfData = $trimpos > 0 ? substr($data, $trimpos) : $data; + // Keep the original byte layout to preserve absolute xref offsets. + // Some PDFs contain bytes before %PDF- and xref offsets still target the full file. + $pdfData = $data; // get xref and trailer data $xref = $this->getXrefData($pdfData); diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 7c7fe7e68..e192a9170 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -111,4 +111,11 @@ public function testPDFDocEncodingDecode(): void $testSubject = '•†‡…—–ƒ⁄‹›−‰„“”‘’‚™ŁŒŠŸŽıłœšž'; self::assertStringContainsString($testSubject, $details['Subject']); } + + public function testParseFileWithCompressedObjRefInXrefStream(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequestInvalidObjectReference.pdf'); + + self::assertSame(1, count($document->getPages())); + } } From be240ba9a38fa66d8b528ac977d13a8b7452c3b6 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Thu, 23 Apr 2026 23:59:46 -0300 Subject: [PATCH 06/47] fix: allow startxref offset to include leading whitespace Some PDFs set startxref to the whitespace immediately before the xref keyword instead of the first letter of xref. The parser required an exact match and incorrectly switched to xref stream decoding, which then failed with Invalid object reference. Changes: - Skip PDF whitespace before checking startxref position - Use adjusted offset when decoding classic xref - Apply same whitespace tolerance for Unix line-ending detection - Tighten trailer key regexes to match /Size /Root /Encrypt /Info /Prev - Add regression fixture and integration test Regression fixture: - samples/bugs/PullRequestXrefWhitespaceStart.pdf Test: - DocumentIssueFocusTest::testParseFileWhenStartxrefPointsToLeadingWhitespace Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .../bugs/PullRequestXrefWhitespaceStart.pdf | Bin 0 -> 6499 bytes .../PdfParser/RawData/RawDataParser.php | 20 +++++++++++------- .../Integration/DocumentIssueFocusTest.php | 7 ++++++ 3 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 samples/bugs/PullRequestXrefWhitespaceStart.pdf diff --git a/samples/bugs/PullRequestXrefWhitespaceStart.pdf b/samples/bugs/PullRequestXrefWhitespaceStart.pdf new file mode 100644 index 0000000000000000000000000000000000000000..718557609b254ab33923a92168582a720f6a4cf2 GIT binary patch literal 6499 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 OTq 0) { + if (preg_match('/\/Size[\s]+([0-9]+)/i', $trailer_data, $matches) > 0) { $xref['trailer']['size'] = (int) $matches[1]; } - if (preg_match('/Root[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { + if (preg_match('/\/Root[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { $xref['trailer']['root'] = (int) $matches[1].'_'.(int) $matches[2]; } - if (preg_match('/Encrypt[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { + if (preg_match('/\/Encrypt[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { $xref['trailer']['encrypt'] = (int) $matches[1].'_'.(int) $matches[2]; } - if (preg_match('/Info[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { + if (preg_match('/\/Info[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { $xref['trailer']['info'] = (int) $matches[1].'_'.(int) $matches[2]; } if (preg_match('/ID[\s]*[\[][\s]*[<]([^>]*)[>][\s]*[<]([^>]*)[>]/i', $trailer_data, $matches) > 0) { @@ -216,7 +216,7 @@ protected function decodeXref(string $pdfData, int $startxref, array $xref = [], $xref['trailer']['id'][1] = $matches[2]; } } - if (preg_match('/Prev[\s]+([0-9]+)/i', $trailer_data, $matches) > 0) { + if (preg_match('/\/Prev[\s]+([0-9]+)/i', $trailer_data, $matches) > 0) { $offset = (int) $matches[1]; if (0 != $offset) { // get previous xref @@ -922,14 +922,18 @@ protected function getXrefData(string $pdfData, int $offset = 0, array $xref = [ throw new \Exception('Unable to find xref (PDF corrupted?)'); } + // Some files point startxref to the whitespace right before the xref keyword. + $startxrefOffset = $startxref + strspn($pdfData, $this->config->getPdfWhitespaces(), $startxref); + // check xref position - if (strpos($pdfData, 'xref', $startxref) == $startxref) { + if (strpos($pdfData, 'xref', $startxrefOffset) == $startxrefOffset) { // Cross-Reference - $xref = $this->decodeXref($pdfData, $startxref, $xref, $visitedOffsets); + $xref = $this->decodeXref($pdfData, $startxrefOffset, $xref, $visitedOffsets); } else { // Check if the $pdfData might have the wrong line-endings $pdfDataUnix = str_replace("\r\n", "\n", $pdfData); - if ($startxref < \strlen($pdfDataUnix) && strpos($pdfDataUnix, 'xref', $startxref) == $startxref) { + $startxrefUnixOffset = $startxref + strspn($pdfDataUnix, $this->config->getPdfWhitespaces(), $startxref); + if ($startxrefUnixOffset < \strlen($pdfDataUnix) && strpos($pdfDataUnix, 'xref', $startxrefUnixOffset) == $startxrefUnixOffset) { // Return Unix-line-ending flag $xref = ['Unix' => true]; } else { diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 7c7fe7e68..bd85d8cbe 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -111,4 +111,11 @@ public function testPDFDocEncodingDecode(): void $testSubject = '•†‡…—–ƒ⁄‹›−‰„“”‘’‚™ŁŒŠŸŽıłœšž'; self::assertStringContainsString($testSubject, $details['Subject']); } + + public function testParseFileWhenStartxrefPointsToLeadingWhitespace(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequestXrefWhitespaceStart.pdf'); + + self::assertSame(1, count($document->getPages())); + } } From 917ad5d7ea24781521c44c10efa6cd2f5a4a497e Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 00:04:37 -0300 Subject: [PATCH 07/47] test: use assertCount for page count assertion Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- tests/PHPUnit/Integration/DocumentIssueFocusTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index e192a9170..54a9dfbd2 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -116,6 +116,6 @@ public function testParseFileWithCompressedObjRefInXrefStream(): void { $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequestInvalidObjectReference.pdf'); - self::assertSame(1, count($document->getPages())); + self::assertCount(1, $document->getPages()); } } From 583526e5e4a901fb0f00e273e3836dc69d963995 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 00:05:13 -0300 Subject: [PATCH 08/47] test: use assertCount for page count assertion Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- tests/PHPUnit/Integration/DocumentIssueFocusTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index bd85d8cbe..836bc7a17 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -116,6 +116,6 @@ public function testParseFileWhenStartxrefPointsToLeadingWhitespace(): void { $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequestXrefWhitespaceStart.pdf'); - self::assertSame(1, count($document->getPages())); + self::assertCount(1, $document->getPages()); } } From 499baa025547df49e60dd11e349e284435c0eef6 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 00:12:50 -0300 Subject: [PATCH 09/47] fix: tolerate startxref offset inside xref keyword Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- ...PullRequestStartxrefWhitespaceXrefStream.pdf | Bin 0 -> 9393 bytes src/Smalot/PdfParser/RawData/RawDataParser.php | 16 ++++++++++++---- .../Integration/DocumentIssueFocusTest.php | 7 +++++++ 3 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 samples/bugs/PullRequestStartxrefWhitespaceXrefStream.pdf diff --git a/samples/bugs/PullRequestStartxrefWhitespaceXrefStream.pdf b/samples/bugs/PullRequestStartxrefWhitespaceXrefStream.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9d15f2474e107c6029772e2ef2107e7d59458dac GIT binary patch literal 9393 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 literal 0 HcmV?d00001 diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index ec8d01e53..746dcd469 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -922,19 +922,27 @@ protected function getXrefData(string $pdfData, int $offset = 0, array $xref = [ throw new \Exception('Unable to find xref (PDF corrupted?)'); } + // Some files point startxref to the whitespace right before the xref keyword or stream object. + $startxrefOffset = $startxref + strspn($pdfData, $this->config->getPdfWhitespaces(), $startxref); + // Be tolerant if startxref points one byte into the xref keyword ("ref"). + if ($startxrefOffset > 0 && strpos($pdfData, 'xref', $startxrefOffset - 1) == $startxrefOffset - 1) { + --$startxrefOffset; + } + // check xref position - if (strpos($pdfData, 'xref', $startxref) == $startxref) { + if (strpos($pdfData, 'xref', $startxrefOffset) == $startxrefOffset) { // Cross-Reference - $xref = $this->decodeXref($pdfData, $startxref, $xref, $visitedOffsets); + $xref = $this->decodeXref($pdfData, $startxrefOffset, $xref, $visitedOffsets); } else { // Check if the $pdfData might have the wrong line-endings $pdfDataUnix = str_replace("\r\n", "\n", $pdfData); - if ($startxref < \strlen($pdfDataUnix) && strpos($pdfDataUnix, 'xref', $startxref) == $startxref) { + $startxrefUnixOffset = $startxref + strspn($pdfDataUnix, $this->config->getPdfWhitespaces(), $startxref); + if ($startxrefUnixOffset < \strlen($pdfDataUnix) && strpos($pdfDataUnix, 'xref', $startxrefUnixOffset) == $startxrefUnixOffset) { // Return Unix-line-ending flag $xref = ['Unix' => true]; } else { // Cross-Reference Stream - $xref = $this->decodeXrefStream($pdfData, $startxref, $xref, $visitedOffsets); + $xref = $this->decodeXrefStream($pdfData, $startxrefOffset, $xref, $visitedOffsets); } } if (empty($xref)) { diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 7c7fe7e68..57a197677 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -111,4 +111,11 @@ public function testPDFDocEncodingDecode(): void $testSubject = '•†‡…—–ƒ⁄‹›−‰„“”‘’‚™ŁŒŠŸŽıłœšž'; self::assertStringContainsString($testSubject, $details['Subject']); } + + public function testParseFileWhenStartxrefPointsToLeadingWhitespaceInXrefStream(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequestStartxrefWhitespaceXrefStream.pdf'); + + self::assertCount(1, $document->getPages()); + } } From 073e5d6642b1cf4becb21c696fe563ae6aa8d53d Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 00:15:17 -0300 Subject: [PATCH 10/47] fix: accept multi-space xref subsection entries Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .../PullRequestXrefSubsectionMultipleSpaces.pdf | Bin 0 -> 2541 bytes src/Smalot/PdfParser/RawData/RawDataParser.php | 2 +- .../Integration/DocumentIssueFocusTest.php | 7 +++++++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 samples/bugs/PullRequestXrefSubsectionMultipleSpaces.pdf diff --git a/samples/bugs/PullRequestXrefSubsectionMultipleSpaces.pdf b/samples/bugs/PullRequestXrefSubsectionMultipleSpaces.pdf new file mode 100644 index 0000000000000000000000000000000000000000..508c197476937691574c8152d80bc4bdf6dbec27 GIT binary patch literal 2541 zcmbtWU2fwx5N^>o0lmY(ivS4RI{W*d&wp8r0fl`2ht=;}WRkA5 zkU%CYu0GZ|6B+lQ=xgn zHMhv!X09vK@6+o8t{*gz`)|vF#~+1;xmc#zWvc~ga@qRLo6>195|8P-7b)&u-rvVB zALAfty&YIqzYNQDvBoe^u2-1~%gYu=HX_7#Vrv|>B;@Jo zsr}Sx=Wd1+_rje)2!BB5fL7COx{FqnLvZ?qv=2QQKZH+NcB56`lLcrQPEV$GI)+fzRjJIEp^K6mJHP2!(xZ1llt%e;jbQ<*j1LZy6 zOtq`pwc~tk=n&TKG{}axGEX+Kkb{o>PNd66tPfP_vgUS!u|6 zE#=orzU51t2e({`OoM|$pIKxi^WrKm;eq0}7kJ>i&Ib!cpQQYReI``Ck+D#K^9BbB z8ReNqI0e-pni<=6l$Zd!!BkHY6JJ^6mo!oEVCc;-(kR~`8`jv!43+)PRIdb_i?R^0 z7746{QV0_Q4kLvoqvA)w6Cp!T8fBPfOS2i5Alt0xI1YK1faKXyK$dGz0>z5Qo51`T zI4JbT01Bs;XkYBB;~94NCB>f*)bBM>+8}BczQ$7uwOQ#9aG0!4!}?#slJ}y-I+)y> zRWx2lG13eZ#YqDEG;r?}aGk{Abd1vxuFi`z2FgyOc2A+!IUG=p(-CUC;u|HPYctz@ zg}ke2oqSFFfMyQi2o2{H8G;rH4|0=g?1NO{q36=B0@#`|+mzgH)W&Tx_slIRar-u( zYmV=)s&2OIBUe}6%|@@%%(U;WVYfKjPN{I}_d^2BySbLY2rtrAzBGM?TG)wj2M$}R zH-*TCb#K=?!7Dx0C>FEpnm^-(1>~;k+?}SE0w)UI*1syTLo+I_uWqQW^=4a@QYaIbq3HMIpe_f9XgtLkvE=n>DAb|>M?iX)1KE0 Yt_B~>OsR%fbu12JzIApszL{A60{WxZ%m4rY literal 0 HcmV?d00001 diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index ec8d01e53..0df21551c 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -169,7 +169,7 @@ protected function decodeXref(string $pdfData, int $startxref, array $xref = [], // initialize object number $obj_num = 0; // search for cross-reference entries or subsection - while (preg_match('/([0-9]+)[\x20]([0-9]+)[\x20]?([nf]?)(\r\n|[\x20]?[\r\n])/', $pdfData, $matches, \PREG_OFFSET_CAPTURE, $offset) > 0) { + while (preg_match('/([0-9]+)[\x20]+([0-9]+)[\x20]*([nf]?)(\r\n|[\x20]*[\r\n])/', $pdfData, $matches, \PREG_OFFSET_CAPTURE, $offset) > 0) { if ($matches[0][1] != $offset) { // we are on another section break; diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 7c7fe7e68..3d5d3de56 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -111,4 +111,11 @@ public function testPDFDocEncodingDecode(): void $testSubject = '•†‡…—–ƒ⁄‹›−‰„“”‘’‚™ŁŒŠŸŽıłœšž'; self::assertStringContainsString($testSubject, $details['Subject']); } + + public function testParseFileWithXrefSubsectionHavingMultipleSpaces(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequestXrefSubsectionMultipleSpaces.pdf'); + + self::assertCount(1, $document->getPages()); + } } From 223536fdee7fa0b9fa4d2f0d67d52ea84c9a7e21 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 00:37:23 -0300 Subject: [PATCH 11/47] fix: support multi-space object headers Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .../PullRequestNearbyObjectHeaderOffset.pdf | Bin 0 -> 2540 bytes .../PdfParser/RawData/RawDataParser.php | 27 +++++++++++++++--- .../Integration/DocumentIssueFocusTest.php | 7 +++++ 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 samples/bugs/PullRequestNearbyObjectHeaderOffset.pdf diff --git a/samples/bugs/PullRequestNearbyObjectHeaderOffset.pdf b/samples/bugs/PullRequestNearbyObjectHeaderOffset.pdf new file mode 100644 index 0000000000000000000000000000000000000000..950fb8f57140569b5abc17603fda6c0b86085e29 GIT binary patch literal 2540 zcmbtWU2fwx5N^>o0lfp^MSui_Oj5QKNpQ4??HF4$-ULaC76|%4OSGe1TNFsTQF4~v zsSmwDdyx($S(Y8O*rIwcs87R>-wfx+C%4m?P5VRZlQkMyc$Tg; zmk7_+O!Fy^MZzt7&9jw$LcSG6meP{5jaB^i%~$YzZSgFrAy^p}I%xAfyyP6=IoB*< znpyaMyU-={^Za^G><2CC(fcB2@n^2lg0Ir-qSr%da?$(Aos)S!;ZNy@SIO^RKR(2- zpW`6uy^kzwRD{JQ-@q}b*sL=Z78gARa(D=91LIy~p^;3M;oWpr+rZmJ?@8-C#Q6F7 zx&J)q3%SBH2m(wT>^L@9*y<(Itgtin&QMewQ?6o}<~kJ_GMsE7w%Q1-4$qS%Gm=}} zEKN5hyZMGQh0~;z1ca4!m@}y(I>PN&IIsC0i)<<6hGj92#*JAUHR`aD(~|ceBsY39 z)h}b$kHyBw!L&bUi4AY1NVYMT(ZK$|)76t!rw{Wp1ZjnKpAhYz_etMHr>z(Om92$X zD?@x%y0GW^KjPu)yTunQ2k~Sl9_+#iq^}n80d#ceufKkg{A0HAvKo+2p@1TX5Z@+_ z?f4IrgoK3D{|GI`EcDF45A$nChK*mQF9JnhHcxg%uiuR%>%NnxY z)^bNF-?9~Sgj*(grjY}k&?A9&H*k?Zbbhg*>XVdp;CEb!t&F)s&~c!p z;EBjI&?yAH$PfZnHxuV=FEIj?g?~sBg&qgS9*&xbEy$s*os=AGP4$|iQ(oje);vKQ zt`zWu=w|T=5R`2<3ut>ROVEmET(YvXYcvxYDGv1sH=3Zu3sPye0=nm?RC8NFv*P`; zCMIqblUvDuMM1T$)RC6D;NQeauC{9(B4{G(ZeIV87k}ghcyFTL4xZm}NSY~aS_op@ z%;#Oql^gq8Iqx9WB2QyPXg96bMO%5Xr}a8$<2BnVjy#*%{u}CDTr2-8>3cf2gARHW zzC@ZUxX~@#UWif!eOE}kJi*q4+9vFFD?G!tcGrwZ3EOLrt{JS~M1FX1bUE*CwtAgr zCUbYWS`*dzQW90`y$c7Uxf-Pt7^7>kGU*0&u&clwJF3Or^~2;UBwtzt(V<1^hdRh}-GPgi-_{rn zJlJL)lr}XR^6ws+{6lhKShrta^-l=l~0GRcNt7B2hTM8|$;wYXATM literal 0 HcmV?d00001 diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index ec8d01e53..4dad74d72 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -513,7 +513,7 @@ protected function decodeXrefStream(string $pdfData, int $startxref, array $xref protected function getObjectHeaderPattern(array $objRefs): string { // consider all whitespace character (PDF specifications) - return '/'.$objRefs[0].$this->config->getPdfWhitespacesRegex().$objRefs[1].$this->config->getPdfWhitespacesRegex().'obj/'; + return '/'.$objRefs[0].$this->config->getPdfWhitespacesRegex().'+'.$objRefs[1].$this->config->getPdfWhitespacesRegex().'+obj/'; } protected function getObjectHeaderLen(array $objRefs): int @@ -546,6 +546,7 @@ protected function getIndirectObject(string $pdfData, array $xref, string $objRe throw new \Exception('Invalid object reference for $obj.'); } + $objHeaderPattern = $this->getObjectHeaderPattern($objRefArr); $objHeaderLen = $this->getObjectHeaderLen($objRefArr); /* @@ -555,9 +556,27 @@ protected function getIndirectObject(string $pdfData, array $xref, string $objRe $offset += strspn($pdfData, $this->config->getPdfWhitespaces(), $offset); // ignore leading zeros for object number $offset += strspn($pdfData, '0', $offset); - if (0 == preg_match($this->getObjectHeaderPattern($objRefArr), substr($pdfData, $offset, $objHeaderLen))) { - // an indirect reference to an undefined object shall be considered a reference to the null object - return ['null', 'null', $offset]; + if (0 == preg_match($objHeaderPattern, substr($pdfData, $offset, 33), $headerMatches)) { + // Some malformed files have slightly inaccurate xref offsets. + // Try to recover by locating the expected object header nearby. + $searchStart = max(0, $offset - 64); + $searchLen = 192; + if ( + preg_match( + $objHeaderPattern, + substr($pdfData, $searchStart, $searchLen), + $headerMatches, + \PREG_OFFSET_CAPTURE + ) > 0 + ) { + $offset = $searchStart + $headerMatches[0][1]; + $objHeaderLen = \strlen($headerMatches[0][0]); + } else { + // an indirect reference to an undefined object shall be considered a reference to the null object + return ['null', 'null', $offset]; + } + } else { + $objHeaderLen = \strlen($headerMatches[0]); } /* diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 7c7fe7e68..843513b50 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -111,4 +111,11 @@ public function testPDFDocEncodingDecode(): void $testSubject = '•†‡…—–ƒ⁄‹›−‰„“”‘’‚™ŁŒŠŸŽıłœšž'; self::assertStringContainsString($testSubject, $details['Subject']); } + + public function testParseFileWhenObjectHeaderIsNearXrefOffset(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequestNearbyObjectHeaderOffset.pdf'); + + self::assertCount(1, $document->getPages()); + } } From 2186082d20a8d01e59c9e9f0f99b5f6d96e12898 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 00:45:48 -0300 Subject: [PATCH 12/47] Guard stream decoding under low memory Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/Smalot/PdfParser/RawData/FilterHelper.php | 56 +++++++++++++++++- .../PdfParser/RawData/RawDataParser.php | 59 ++++++++++++++++++- .../Integration/DocumentIssueFocusTest.php | 7 +++ 3 files changed, 118 insertions(+), 4 deletions(-) diff --git a/src/Smalot/PdfParser/RawData/FilterHelper.php b/src/Smalot/PdfParser/RawData/FilterHelper.php index 87f5524d7..9c978a5c7 100644 --- a/src/Smalot/PdfParser/RawData/FilterHelper.php +++ b/src/Smalot/PdfParser/RawData/FilterHelper.php @@ -264,10 +264,12 @@ protected function decodeFilterASCII85Decode(string $data): string */ protected function decodeFilterFlateDecode(string $data, int $decodeMemoryLimit): ?string { + $effectiveDecodeMemoryLimit = $this->getEffectiveDecodeMemoryLimit($decodeMemoryLimit); + // Uncatchable E_WARNING for "data error" is @ suppressed // so execution may proceed with an alternate decompression // method. - $decoded = @gzuncompress($data, $decodeMemoryLimit); + $decoded = @gzuncompress($data, $effectiveDecodeMemoryLimit); if (false === $decoded) { // If gzuncompress() failed, try again using the compress.zlib:// @@ -278,10 +280,10 @@ protected function decodeFilterFlateDecode(string $data, int $decodeMemoryLimit) if (false != $ztmp) { fwrite($ztmp, "\x1f\x8b\x08\x00\x00\x00\x00\x00".$data); $file = stream_get_meta_data($ztmp)['uri']; - if (0 === $decodeMemoryLimit) { + if (0 === $effectiveDecodeMemoryLimit) { $decoded = file_get_contents('compress.zlib://'.$file); } else { - $decoded = file_get_contents('compress.zlib://'.$file, false, null, 0, $decodeMemoryLimit); + $decoded = file_get_contents('compress.zlib://'.$file, false, null, 0, $effectiveDecodeMemoryLimit); } fclose($ztmp); } @@ -295,6 +297,54 @@ protected function decodeFilterFlateDecode(string $data, int $decodeMemoryLimit) return $decoded; } + private function getEffectiveDecodeMemoryLimit(int $decodeMemoryLimit): int + { + if ($decodeMemoryLimit > 0) { + return $decodeMemoryLimit; + } + + $memoryLimit = $this->parseIniMemoryLimit((string) ini_get('memory_limit')); + if ($memoryLimit <= 0) { + // Unlimited PHP memory limit. + return 0; + } + + // Keep substantial headroom because zlib decoding can transiently allocate + // more memory than the returned string. + $available = $memoryLimit - memory_get_usage(true); + if ($available <= (16 * 1024 * 1024)) { + return 1024 * 1024; + } + + $safeLimit = (int) floor(($available - (8 * 1024 * 1024)) / 2); + + return (int) min(max($safeLimit, 1024 * 1024), 256 * 1024 * 1024); + } + + private function parseIniMemoryLimit(string $value): int + { + $value = trim($value); + if ('' === $value || '-1' === $value) { + return -1; + } + + $unit = strtolower(substr($value, -1)); + $number = (int) $value; + switch ($unit) { + case 'g': + return $number * 1024 * 1024 * 1024; + + case 'm': + return $number * 1024 * 1024; + + case 'k': + return $number * 1024; + + default: + return (int) $value; + } + } + /** * LZWDecode * diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index ec8d01e53..a426a2a89 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -778,7 +778,9 @@ protected function getRawObject(string $pdfData, int $offset = 0, ?array $header // we get stream length here to later help preg_match test less data $streamLen = (int) $this->getHeaderValue($headerDic, 'Length', 'numeric', 0); - $skip = false === $this->config->getRetainImageContent() && 'XObject' == $this->getHeaderValue($headerDic, 'Type', '/') && 'Image' == $this->getHeaderValue($headerDic, 'Subtype', '/'); + $skip = (false === $this->config->getRetainImageContent() || $this->shouldSkipImageStreamContent($headerDic)) + && 'XObject' == $this->getHeaderValue($headerDic, 'Type', '/') + && 'Image' == $this->getHeaderValue($headerDic, 'Subtype', '/'); $pregResult = preg_match( '/(endstream)[\x09\x0a\x0c\x0d\x20]/isU', @@ -819,6 +821,61 @@ protected function getRawObject(string $pdfData, int $offset = 0, ?array $header return [$objtype, $objval, $offset]; } + private function shouldSkipImageStreamContent(array $headerDic): bool + { + $memoryLimit = $this->getMemoryLimitBytes(); + if ($memoryLimit <= 0) { + return false; + } + + if ('XObject' != $this->getHeaderValue($headerDic, 'Type', '/') || 'Image' != $this->getHeaderValue($headerDic, 'Subtype', '/')) { + return false; + } + + if ($memoryLimit <= (256 * 1024 * 1024)) { + return true; + } + + return memory_get_usage(true) >= (int) floor($memoryLimit * 0.8); + } + + private function getMemoryLimitBytes(): int + { + static $memoryLimit = null; + if (null !== $memoryLimit) { + return $memoryLimit; + } + + $value = trim((string) ini_get('memory_limit')); + if ('' === $value || '-1' === $value) { + $memoryLimit = -1; + + return $memoryLimit; + } + + $unit = strtolower(substr($value, -1)); + $number = (int) $value; + switch ($unit) { + case 'g': + $memoryLimit = $number * 1024 * 1024 * 1024; + break; + + case 'm': + $memoryLimit = $number * 1024 * 1024; + break; + + case 'k': + $memoryLimit = $number * 1024; + break; + + default: + $memoryLimit = (int) $value; + break; + } + + return $memoryLimit; + } + /** * Get value of an object header's section (obj << YYY >> part ). * diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 7c7fe7e68..3517ab7a3 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -111,4 +111,11 @@ public function testPDFDocEncodingDecode(): void $testSubject = '•†‡…—–ƒ⁄‹›−‰„“”‘’‚™ŁŒŠŸŽıłœšž'; self::assertStringContainsString($testSubject, $details['Subject']); } + + public function testParseFileWithLargeFlateStreams(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest457.pdf'); + + self::assertCount(28, $document->getPages()); + } } From 1a2e8c8c68bd0c5225533f33f17ae14cbdafa70d Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 00:51:03 -0300 Subject: [PATCH 13/47] Fix null header handling in stream skip guard Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/Smalot/PdfParser/RawData/RawDataParser.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index a426a2a89..9bcf91e87 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -821,8 +821,12 @@ protected function getRawObject(string $pdfData, int $offset = 0, ?array $header return [$objtype, $objval, $offset]; } - private function shouldSkipImageStreamContent(array $headerDic): bool + private function shouldSkipImageStreamContent(?array $headerDic): bool { + if (false === \is_array($headerDic)) { + return false; + } + $memoryLimit = $this->getMemoryLimitBytes(); if ($memoryLimit <= 0) { return false; From faccd50521b762ffa4cda413c9f57005dc5102ad Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 00:53:09 -0300 Subject: [PATCH 14/47] Refactor duplicated memory limit parsing Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/Smalot/PdfParser/RawData/FilterHelper.php | 27 +---------- src/Smalot/PdfParser/RawData/MemoryLimit.php | 45 +++++++++++++++++++ .../PdfParser/RawData/RawDataParser.php | 27 +---------- 3 files changed, 47 insertions(+), 52 deletions(-) create mode 100644 src/Smalot/PdfParser/RawData/MemoryLimit.php diff --git a/src/Smalot/PdfParser/RawData/FilterHelper.php b/src/Smalot/PdfParser/RawData/FilterHelper.php index 9c978a5c7..88c4f12ad 100644 --- a/src/Smalot/PdfParser/RawData/FilterHelper.php +++ b/src/Smalot/PdfParser/RawData/FilterHelper.php @@ -303,7 +303,7 @@ private function getEffectiveDecodeMemoryLimit(int $decodeMemoryLimit): int return $decodeMemoryLimit; } - $memoryLimit = $this->parseIniMemoryLimit((string) ini_get('memory_limit')); + $memoryLimit = MemoryLimit::toBytes((string) ini_get('memory_limit')); if ($memoryLimit <= 0) { // Unlimited PHP memory limit. return 0; @@ -320,31 +320,6 @@ private function getEffectiveDecodeMemoryLimit(int $decodeMemoryLimit): int return (int) min(max($safeLimit, 1024 * 1024), 256 * 1024 * 1024); } - - private function parseIniMemoryLimit(string $value): int - { - $value = trim($value); - if ('' === $value || '-1' === $value) { - return -1; - } - - $unit = strtolower(substr($value, -1)); - $number = (int) $value; - switch ($unit) { - case 'g': - return $number * 1024 * 1024 * 1024; - - case 'm': - return $number * 1024 * 1024; - - case 'k': - return $number * 1024; - - default: - return (int) $value; - } - } - /** * LZWDecode * diff --git a/src/Smalot/PdfParser/RawData/MemoryLimit.php b/src/Smalot/PdfParser/RawData/MemoryLimit.php new file mode 100644 index 000000000..bbb9160fe --- /dev/null +++ b/src/Smalot/PdfParser/RawData/MemoryLimit.php @@ -0,0 +1,45 @@ + + * + * @date 2026-04-24 + * + * @license LGPLv3 + * + * @url + */ + +namespace Smalot\PdfParser\RawData; + +final class MemoryLimit +{ + /** + * Converts PHP ini memory values (for example "128M", "1G", "-1") to bytes. + */ + public static function toBytes(string $value): int + { + $value = trim($value); + if ('' === $value || '-1' === $value) { + return -1; + } + + $unit = strtolower(substr($value, -1)); + $number = (int) $value; + switch ($unit) { + case 'g': + return $number * 1024 * 1024 * 1024; + + case 'm': + return $number * 1024 * 1024; + + case 'k': + return $number * 1024; + + default: + return (int) $value; + } + } +} \ No newline at end of file diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index 9bcf91e87..12fdc2b6f 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -850,32 +850,7 @@ private function getMemoryLimitBytes(): int return $memoryLimit; } - $value = trim((string) ini_get('memory_limit')); - if ('' === $value || '-1' === $value) { - $memoryLimit = -1; - - return $memoryLimit; - } - - $unit = strtolower(substr($value, -1)); - $number = (int) $value; - switch ($unit) { - case 'g': - $memoryLimit = $number * 1024 * 1024 * 1024; - break; - - case 'm': - $memoryLimit = $number * 1024 * 1024; - break; - - case 'k': - $memoryLimit = $number * 1024; - break; - - default: - $memoryLimit = (int) $value; - break; - } + $memoryLimit = MemoryLimit::toBytes((string) ini_get('memory_limit')); return $memoryLimit; } From 83a11f89e56d11f4732279ad24bd452402b85db3 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 00:54:44 -0300 Subject: [PATCH 15/47] Add unit tests for MemoryLimit helper Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- tests/PHPUnit/Unit/MemoryLimitTest.php | 61 ++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 tests/PHPUnit/Unit/MemoryLimitTest.php diff --git a/tests/PHPUnit/Unit/MemoryLimitTest.php b/tests/PHPUnit/Unit/MemoryLimitTest.php new file mode 100644 index 000000000..583cd2f81 --- /dev/null +++ b/tests/PHPUnit/Unit/MemoryLimitTest.php @@ -0,0 +1,61 @@ + + * + * @date 2026-04-24 + * + * @license LGPLv3 + * + * @url + */ + +namespace PHPUnitTests\Unit; + +use PHPUnitTests\TestCase; +use Smalot\PdfParser\RawData\MemoryLimit; + +class MemoryLimitTest extends TestCase +{ + public function testToBytesWithGigabytes(): void + { + $this->assertSame(1073741824, MemoryLimit::toBytes('1G')); + } + + public function testToBytesWithMegabytes(): void + { + $this->assertSame(268435456, MemoryLimit::toBytes('256M')); + } + + public function testToBytesWithKilobytes(): void + { + $this->assertSame(65536, MemoryLimit::toBytes('64K')); + } + + public function testToBytesWithoutUnit(): void + { + $this->assertSame(2048, MemoryLimit::toBytes('2048')); + } + + public function testToBytesTrimsInput(): void + { + $this->assertSame(33554432, MemoryLimit::toBytes(' 32M ')); + } + + public function testToBytesHandlesLowercaseUnits(): void + { + $this->assertSame(1048576, MemoryLimit::toBytes('1m')); + } + + public function testToBytesReturnsMinusOneForUnlimitedValue(): void + { + $this->assertSame(-1, MemoryLimit::toBytes('-1')); + } + + public function testToBytesReturnsMinusOneForEmptyValue(): void + { + $this->assertSame(-1, MemoryLimit::toBytes('')); + } +} From 975feb513a6c38c60aa30af27839a390316cf65c Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 00:58:04 -0300 Subject: [PATCH 16/47] Refactor MemoryLimit test with data provider Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- tests/PHPUnit/Unit/MemoryLimitTest.php | 63 ++++++++++---------------- 1 file changed, 24 insertions(+), 39 deletions(-) diff --git a/tests/PHPUnit/Unit/MemoryLimitTest.php b/tests/PHPUnit/Unit/MemoryLimitTest.php index 583cd2f81..53088ec18 100644 --- a/tests/PHPUnit/Unit/MemoryLimitTest.php +++ b/tests/PHPUnit/Unit/MemoryLimitTest.php @@ -3,7 +3,7 @@ /** * @file This file is part of the PdfParser library. * - * @author Konrad Abicht + * @author Vitor Mattos <1079143+vitormattos@users.noreply.github.com> * * @date 2026-04-24 * @@ -19,43 +19,28 @@ class MemoryLimitTest extends TestCase { - public function testToBytesWithGigabytes(): void - { - $this->assertSame(1073741824, MemoryLimit::toBytes('1G')); - } - - public function testToBytesWithMegabytes(): void - { - $this->assertSame(268435456, MemoryLimit::toBytes('256M')); - } - - public function testToBytesWithKilobytes(): void - { - $this->assertSame(65536, MemoryLimit::toBytes('64K')); - } - - public function testToBytesWithoutUnit(): void - { - $this->assertSame(2048, MemoryLimit::toBytes('2048')); - } - - public function testToBytesTrimsInput(): void - { - $this->assertSame(33554432, MemoryLimit::toBytes(' 32M ')); - } - - public function testToBytesHandlesLowercaseUnits(): void - { - $this->assertSame(1048576, MemoryLimit::toBytes('1m')); - } - - public function testToBytesReturnsMinusOneForUnlimitedValue(): void - { - $this->assertSame(-1, MemoryLimit::toBytes('-1')); - } - - public function testToBytesReturnsMinusOneForEmptyValue(): void - { - $this->assertSame(-1, MemoryLimit::toBytes('')); + /** + * @dataProvider toBytesProvider + */ + public function testToBytes(string $input, int $expected): void + { + $this->assertSame($expected, MemoryLimit::toBytes($input)); + } + + /** + * @return array + */ + public static function toBytesProvider(): array + { + return [ + 'gigabytes' => ['1G', 1073741824], + 'megabytes' => ['256M', 268435456], + 'kilobytes' => ['64K', 65536], + 'without unit' => ['2048', 2048], + 'trimmed value' => [' 32M ', 33554432], + 'lowercase unit' => ['1m', 1048576], + 'unlimited value' => ['-1', -1], + 'empty value' => ['', -1], + ]; } } From 4ec6c0bae6f4a0ad88bdd46eece419a460492b7a Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 01:00:25 -0300 Subject: [PATCH 17/47] Apply cs-fixer formatting for MemoryLimit Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/Smalot/PdfParser/RawData/MemoryLimit.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Smalot/PdfParser/RawData/MemoryLimit.php b/src/Smalot/PdfParser/RawData/MemoryLimit.php index bbb9160fe..8bc3a87f7 100644 --- a/src/Smalot/PdfParser/RawData/MemoryLimit.php +++ b/src/Smalot/PdfParser/RawData/MemoryLimit.php @@ -3,7 +3,7 @@ /** * @file This file is part of the PdfParser library. * - * @author Konrad Abicht + * @author Vitor Mattos <1079143+vitormattos@users.noreply.github.com> * * @date 2026-04-24 * @@ -42,4 +42,4 @@ public static function toBytes(string $value): int return (int) $value; } } -} \ No newline at end of file +} From 7434c94a473d194aebae5c5e72c20cf813d15ae1 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 01:01:59 -0300 Subject: [PATCH 18/47] Reduce memory usage in large flate regression test Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- tests/PHPUnit/Integration/DocumentIssueFocusTest.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 3517ab7a3..9aac7c08f 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -36,6 +36,7 @@ namespace PHPUnitTests\Integration; use PHPUnitTests\TestCase; +use Smalot\PdfParser\Config; use Smalot\PdfParser\Document; use Smalot\PdfParser\Parser; @@ -114,7 +115,9 @@ public function testPDFDocEncodingDecode(): void public function testParseFileWithLargeFlateStreams(): void { - $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest457.pdf'); + $config = new Config(); + $config->setRetainImageContent(false); + $document = (new Parser([], $config))->parseFile($this->rootDir.'/samples/bugs/PullRequest457.pdf'); self::assertCount(28, $document->getPages()); } From 10c7ffab9cdf85c4b9dded3484aa1e191faf709b Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 01:05:09 -0300 Subject: [PATCH 19/47] Lower decode memory cap in large flate test Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- tests/PHPUnit/Integration/DocumentIssueFocusTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 9aac7c08f..708aaba0a 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -117,6 +117,7 @@ public function testParseFileWithLargeFlateStreams(): void { $config = new Config(); $config->setRetainImageContent(false); + $config->setDecodeMemoryLimit(8 * 1024 * 1024); $document = (new Parser([], $config))->parseFile($this->rootDir.'/samples/bugs/PullRequest457.pdf'); self::assertCount(28, $document->getPages()); From 6aa65941b07db163ace64775b3b4855315a90d48 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 01:10:09 -0300 Subject: [PATCH 20/47] Mark large flate regression as linux-only Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- tests/PHPUnit/Integration/DocumentIssueFocusTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 708aaba0a..82dad54f8 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -113,6 +113,9 @@ public function testPDFDocEncodingDecode(): void self::assertStringContainsString($testSubject, $details['Subject']); } + /** + * @group linux-only + */ public function testParseFileWithLargeFlateStreams(): void { $config = new Config(); From 80c47be2de9edf49d67dda5d22f14e4bdf274057 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 01:15:17 -0300 Subject: [PATCH 21/47] Reduce memory use in PullRequest457 page test Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- tests/PHPUnit/Integration/PageTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/PHPUnit/Integration/PageTest.php b/tests/PHPUnit/Integration/PageTest.php index 33751e599..371fbdb9c 100644 --- a/tests/PHPUnit/Integration/PageTest.php +++ b/tests/PHPUnit/Integration/PageTest.php @@ -154,7 +154,9 @@ public function testGetTextPullRequest457(): void { // Document with text. $filename = $this->rootDir.'/samples/bugs/PullRequest457.pdf'; - $parser = $this->getParserInstance(); + $config = new Config(); + $config->setRetainImageContent(false); + $parser = $this->getParserInstance($config); $document = $parser->parseFile($filename); $pages = $document->getPages(); $page = $pages[0]; From 5be65722140f74da66d932b4fcb6ad55c4957333 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 01:18:17 -0300 Subject: [PATCH 22/47] Mark PullRequest457 page test as linux-only Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- tests/PHPUnit/Integration/PageTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/PHPUnit/Integration/PageTest.php b/tests/PHPUnit/Integration/PageTest.php index 371fbdb9c..8c709e588 100644 --- a/tests/PHPUnit/Integration/PageTest.php +++ b/tests/PHPUnit/Integration/PageTest.php @@ -147,6 +147,7 @@ public function testGetText(): void /** * @group memory-heavy + * @group linux-only * * @see https://github.com/smalot/pdfparser/pull/457 */ From 602251d19a2c86356390c2ef855edbec4f44eb9c Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 01:27:26 -0300 Subject: [PATCH 23/47] test: stabilize windows low-memory PHPUnit run Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- tests/PHPUnit/Integration/PageTest.php | 2 +- tests/PHPUnit/Integration/ParserTest.php | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/PHPUnit/Integration/PageTest.php b/tests/PHPUnit/Integration/PageTest.php index 8c709e588..496a280fe 100644 --- a/tests/PHPUnit/Integration/PageTest.php +++ b/tests/PHPUnit/Integration/PageTest.php @@ -147,7 +147,7 @@ public function testGetText(): void /** * @group memory-heavy - * @group linux-only + * @group linux-only * * @see https://github.com/smalot/pdfparser/pull/457 */ diff --git a/tests/PHPUnit/Integration/ParserTest.php b/tests/PHPUnit/Integration/ParserTest.php index 046bf4317..4489c3205 100644 --- a/tests/PHPUnit/Integration/ParserTest.php +++ b/tests/PHPUnit/Integration/ParserTest.php @@ -54,6 +54,7 @@ protected function setUp(): void * Notice: it may fail to run in Scrutinizer because of memory limitations. * * @group memory-heavy + * @group linux-only */ public function testParseFile(): void { @@ -375,8 +376,7 @@ public function testRetainImageContentImpact(): void $document = $this->fixture->parseFile($filename); } - $usedMemory = memory_get_usage(true); - $this->assertGreaterThan($baselineMemory + 180000000, $usedMemory, 'Memory is only '.$usedMemory); + $memoryWithRetainedImages = memory_get_usage(true); $this->assertTrue(null != $document && '' !== $document->getText()); // force garbage collection @@ -395,12 +395,13 @@ public function testRetainImageContentImpact(): void $document = $this->fixture->parseFile($filename); } - $usedMemory = memory_get_usage(true); - /* - * note: the following memory value is set manually and may differ from system to system. - * it must be high enough to not produce a false negative though. - */ - $this->assertLessThan($baselineMemory * 1.05, $usedMemory, 'Memory is '.$usedMemory); + $memoryWithoutRetainedImages = memory_get_usage(true); + $this->assertLessThanOrEqual( + $memoryWithRetainedImages, + $memoryWithoutRetainedImages, + 'Discarding image content should not use more memory than retaining it.' + ); + $this->assertGreaterThanOrEqual($baselineMemory, $memoryWithoutRetainedImages); $this->assertTrue('' !== $document->getText()); } From 95e1553213730d592b7536a5758549445a9d739d Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 01:31:25 -0300 Subject: [PATCH 24/47] test: collect garbage after each test Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- tests/PHPUnit/TestCase.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/PHPUnit/TestCase.php b/tests/PHPUnit/TestCase.php index 08d4739a7..bb40dfc39 100644 --- a/tests/PHPUnit/TestCase.php +++ b/tests/PHPUnit/TestCase.php @@ -57,6 +57,19 @@ protected function setUp(): void $this->rootDir = __DIR__.'/../..'; } + protected function tearDown(): void + { + $this->fixture = null; + $this->rootDir = null; + + \gc_collect_cycles(); + if (\function_exists('gc_mem_caches')) { + \gc_mem_caches(); + } + + parent::tearDown(); + } + protected function getDocumentInstance(): Document { return new Document(); From 77dec161f44de1cce198aab208c637da1083fade Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 11:08:02 -0300 Subject: [PATCH 25/47] test: add regression for startxref near xref keyword Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- samples/bugs/PullRequest794.pdf | Bin 0 -> 6499 bytes .../Integration/DocumentIssueFocusTest.php | 7 +++++++ 2 files changed, 7 insertions(+) create mode 100644 samples/bugs/PullRequest794.pdf diff --git a/samples/bugs/PullRequest794.pdf b/samples/bugs/PullRequest794.pdf new file mode 100644 index 0000000000000000000000000000000000000000..718557609b254ab33923a92168582a720f6a4cf2 GIT binary patch literal 6499 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 OTqparseFile($this->rootDir.'/samples/bugs/PullRequest794.pdf'); + + self::assertCount(1, $document->getPages()); + } } From e2e47d3168e40d1cd4aa66f93c38748d1a2c3d52 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 11:08:02 -0300 Subject: [PATCH 26/47] fix: tolerate startxref offset near xref keyword Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/Smalot/PdfParser/RawData/RawDataParser.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index ec8d01e53..08d7d2bee 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -922,19 +922,27 @@ protected function getXrefData(string $pdfData, int $offset = 0, array $xref = [ throw new \Exception('Unable to find xref (PDF corrupted?)'); } + // Some files point startxref to whitespace right before the xref keyword. + $startxrefOffset = $startxref + strspn($pdfData, $this->config->getPdfWhitespaces(), $startxref); + // Be tolerant when startxref points one byte inside "xref" (e.g. "ref"). + if ($startxrefOffset > 0 && strpos($pdfData, 'xref', $startxrefOffset - 1) == $startxrefOffset - 1) { + --$startxrefOffset; + } + // check xref position - if (strpos($pdfData, 'xref', $startxref) == $startxref) { + if (strpos($pdfData, 'xref', $startxrefOffset) == $startxrefOffset) { // Cross-Reference - $xref = $this->decodeXref($pdfData, $startxref, $xref, $visitedOffsets); + $xref = $this->decodeXref($pdfData, $startxrefOffset, $xref, $visitedOffsets); } else { // Check if the $pdfData might have the wrong line-endings $pdfDataUnix = str_replace("\r\n", "\n", $pdfData); - if ($startxref < \strlen($pdfDataUnix) && strpos($pdfDataUnix, 'xref', $startxref) == $startxref) { + $startxrefUnixOffset = $startxref + strspn($pdfDataUnix, $this->config->getPdfWhitespaces(), $startxref); + if ($startxrefUnixOffset < \strlen($pdfDataUnix) && strpos($pdfDataUnix, 'xref', $startxrefUnixOffset) == $startxrefUnixOffset) { // Return Unix-line-ending flag $xref = ['Unix' => true]; } else { // Cross-Reference Stream - $xref = $this->decodeXrefStream($pdfData, $startxref, $xref, $visitedOffsets); + $xref = $this->decodeXrefStream($pdfData, $startxrefOffset, $xref, $visitedOffsets); } } if (empty($xref)) { From 9acca8dc0106482905336d02115d52369adcba0b Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 11:15:09 -0300 Subject: [PATCH 27/47] test: add second startxref regression sample Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- samples/bugs/PullRequest794.pdf | Bin 0 -> 6499 bytes .../Integration/DocumentIssueFocusTest.php | 7 +++++++ 2 files changed, 7 insertions(+) create mode 100644 samples/bugs/PullRequest794.pdf diff --git a/samples/bugs/PullRequest794.pdf b/samples/bugs/PullRequest794.pdf new file mode 100644 index 0000000000000000000000000000000000000000..718557609b254ab33923a92168582a720f6a4cf2 GIT binary patch literal 6499 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 OTqgetPages()); } + + public function testParseFileWhenStartxrefPointsNearXrefKeyword(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest794.pdf'); + + self::assertCount(1, $document->getPages()); + } } From a3d9df020b26494e759bc90c8b73923740e1b1cd Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 11:59:17 -0300 Subject: [PATCH 28/47] test: add pdf.js compressed xref regression Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- samples/bugs/PullRequest797.pdf | Bin 0 -> 8286 bytes .../Integration/DocumentIssueFocusTest.php | 10 ++++++++++ 2 files changed, 10 insertions(+) create mode 100644 samples/bugs/PullRequest797.pdf diff --git a/samples/bugs/PullRequest797.pdf b/samples/bugs/PullRequest797.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f3e25216d231f4b18c14e33b00bfc7877650c30c GIT binary patch literal 8286 zcmZ{qcU;p+(D0Qip$P~GD2Cn%od8m#9layHgb+FjkkEVYh9XGsMUbvYlMaG(REi*= z2m%TLrS~UzchC9WJ@0-#ncbb=?CkE$>|fuo=_o4m3GxdA*eBC%91(Cu2nq(|RFo7F5EK%?3PCXeu&|&h*KfW> zfAg*E=z_v}1}VE>*D1oF2wNBcqydB5qa1)>iK|6O6m~CHfKLwf@B&eY014iwLycsj z7ws2ZG2~%dN%$`s$uY7aMmSbv{1O_kkXiBh%qga+$6=4&!@>z~cHv~wWYt-(c4RUd z(ECoV57V)uf(%zac{OTlonGfAr(wAY_+NYc75b}?{x|ejiSmG94KDfmhem1Az2kNQ9>c6q{o4Uy6THd^P`jA8d@F`Y;sG z41|p_5M%)J!6r)86l;J>~8MTx8pyH?avbUC)*yL zu&WQhSH**0jYkK9&4eQy!6%P!vHf!=MHmw5;pldiZ^5g(VlSoa=z&BjI6ypr!ot{m zLH?SEfB_&QM_ZHw5{Qk*FH0pjHm8nodmu;?0@XvfLg0UEunz%Y2zR_nIZ*KGef(bj z62D#HuW}F*78m`yHUxnZ!a@R9=lE~={9ZHFCPY4F{f&7o&&1S?ve|~yQLY~vzDTFD zAsW~~?m0ee#+HuuZ@~pNEJpLo^))Rv>fJT`j3qSkL5_LjgW?1yC%Vj=iHUvk^G5M zCsgJ=@?NV4VU)Lvf5~Wp!rt(;^;(8Ud-%@}RtvqO2;M)D0aMO*U_4syG)C*T!QFIj zI9VBWgwJVzIb`YHDsHgDPZ1v}6qBW=LwD0J6TO#-Kkn_OD17Tqh#yja>)L*~%BxE> zixi_`QRI3%p~cOlYb*xW0Xyreh4Nx739p&4W(|D=`0QAMI;F8#$QrK#wrR$c#M zjPkj(Z&~)^q_>>Jk0U+lzY*diXesrx&cAVpbiUQWkHq9;i|7=K4VACdnUk#w*G<+U z=if={ZB5nTzIfQp?M*h~%P5A!($Za9sp|{?RA{^=WXcH*4or`Ioa!iy2Tq|=O~zg7 zd4+KAFnT7O_5kxPan$`U=WbK47jw6SaKmxlT-b&4qjb-RxX$`Zj`-eb;9n!My4eCu*KsAaa=tWjc*Fz--?! z9ld-1&~Y25BdIii_!%*zwxb!~nBgGO*T@dES3^;!`P99BBqF*Q6WDw?9$cMY^=R|t zorHr6*J4BA#P+vmhj8Ao&cMw>Xs}e^aOYMXZSmBgAy_g~#Axt5gCEp=*BHs)AYD+z4%c1MU*O+GaSTf!$&NO}wFi(uD^tmXeL2Mqr zwk5nKdw=eUs~ATn#j2InJYo1(Rw?c4(KY(P0?DM9s>KZzNN?yvT6`&K3x?L$t#Rt} zb1Wh{n~u?26f!(-;P7qT*IKlPw)j7LU>ub={@jpN62~2+H0gDJv+=B**InW`{(jcv z7!e*8>GM#Xu2+0j3KlLvCV|R`q4qByKP(;}3)|DQ+pmqg*$;eOqaDx5K~wG8%g8ZC zUZ%Mt(AV?dNTK~SE%Uu0-QMu)Qp^X*wCX?0-zJ&-pw zuOOXzAGKgCIYa23lzMqwk1@s6$qf~#uzHjW+&vbQR`;V|8p`30 zN)46$Wp>m_VI&m>8=daFb4dXS<4E{YX5_s<7E&=B?$q6us`=K)Mknfi@$_SHdZq_* zX?k!z^>0Bd$MAN(nG*JtEFNcn0}|UCTD9=Ii-$hXQyy+CEO2#HV4TlQ2_!o~B>8wW>*h7hIW{rg&2~&{1aDWQVQK7F>hBck;4Cme$`?5=~{Tcr(8< zf^iLPXcal%iiSJ7(L2OBmdOdk1#}*swXKjG>(>FALqF9LJ;lws#_<$Cu}gE1eMP^4 z>-aNjl{-U?+RAm?1MHx1p-wQ}68|u4Q$PS|x2Tad%BJ>*Zia$$TW|QZ*AG_HqOirt z)aA0Sy)zsm$4uekG@N!i-f(ecnGJsB;Ygan@Q3)zh7V*#lX2Z6b{;3?X}r2dvM9ZR z!bFXI8$QL{ZRK5nd?iIoeivUl>oaA3V`vXQd*3rPnAcwKqCRZKc_!M}99I!H-*$lD z6LQ|2w>cHlA{E(*s+*QMc|XNPlgWIYF0=Wvr9{K07dOaCbIW_x#(Yfnl6F}}l5Qn@ z7P;lpmN4O3YNwKGwH94r%_H!F?nYwaRNV(TdOMX=*)~Jp>J%NjvNBU|J8sWbgDE0) zIVb>EEa`5+S&P3%Ino}vG+2rxZf>z$>E)oEbgiknc0@Cr0vP%DX7PDD)SeGyMzdD0 zy9c)=_7(&r=TW8-DD_d=7HdS)_-FG_>_g^(w5Zm7xNTcvEP=^{niWj9?&tgLZ!fs} zr-7=5kISl;TlPM_A5oL>qDnKD4@fsE`wE9QhZ#}AqPl-5#F^c&+1R;wj3Zw1!EnRZ z(R4L!!R>tMOA8l6>A(_`)lLXJSnyf&3(GuhontTQwCgEHBpJGuy5W@d#hhG)`lI#f zVpdm8 z&%SixOz)x5viMa7X_+fE+EEtyeh#vTm^UhQpjuZpYlSWkM!g+SX^7M#U?;qE?n$dk zYPyNn8T5TrT%uCpW}Mik@yqZJ;VwGiHk*^oQYF$TA`7+C4X5G(W1GDvY_-~!&}}V@ z)(5-!{_US1zXqxtCRtj!L>n$O8Iu}PKa8KUQC*&y+gbv7(+#;Eco-SZ+KJC@8j5=P zH&^!P=;}r;*Tbs&vmW2F3k`)`M|h{LHORSssg`|7Io&v&1@M=6no*Nc4dn6o9-^eb z>qn|vT(i2B$xp+&F1$M!F}BHHqy8jKy)u(KJFU^oiF-(wG@SM`=`D~I4U_|r3$`pG z1}SfEwjEtyc%8Iq_OgO0(2cD^>BFCGQxO?NAF5OuB&rgI3tQfp$bW@Nn2?#a3*NGI z~EPxClJNm)%Iu`VGStgm&4!4| z7it;j3NvZS5^OA{sttzyPWzeau$?RhjQO4DG10p%PDq@@C7ql8_eR4Qs&nO^tQ)sk92cl|25W?POUXhc15O zJOY?2U2*+8k&FvQci-*0f?Sh$v=on>AWC6sg3f?oEM7vb3fB!kB%aZ`KDy6j@XOa_ z_FlSJ!J@?W9H@19XWRVt{OtL#Zl2yCR|}KZ_JyWhT7n)MIVNbuY_FIh@FJ0cVj$SF z`pE_#+io52Ko@HlJHIr`=Z^XGJfFB3K_UZUw%39N1ow)xL)dquWe@8PKda%CM$pTr zZtXwx>+h@mtVhY+KC$+VH|PZ(>*iiPkgf6Ew3654!@LMUVo}4`aE?v{WW2SjP}11D zwSP|EujlrJZ*L7_#{k_Rk;_<^iGQ}yTd>+>hH}}>T&}!E+IGuZ7vuaY7$Yy;8q8=j z=MTyLzBr+V=6zi@2MzB!40lmqG156+*eHOMfowPSSbk*LhQEv~kYnkhL|zjPFxbyn zB~jvDq4(c?%W)8lnist_Jg5?7lSbouo;zci$yuCNgK$|eL6oYbYdO1?a`tDlY09>U z8mvyA);JzJ7pX=5WS<&psD7+btlW0uWbAES`LJJ)S1ILtBbV0Hz#pAWs~B4&e=D<} z``J9`-B`&Leb+Tv;F6+y@ePA8|1)`BNZ9RrT;vdXkge)Slm||0 zWmmt%OOKEcHQ0VC@42>YY|eXNgW;#=n^;os*4QEiPnkRW zv`m=UOh`w}$NGlTl`uq8Pm?*>zlaaC&6}fIQi#;j`sA`S{W7y#Gp?O3ZjBX>I~yw1RGslg_m#fG z)T{=kl`qm0VbQsg$^_ffEjqpiRyow;O4NgBbg^j@{>Rld#!8<-hC?X-yxHgKt|0U6 z>bm2Pxq0ERD*9u$c)oUF>eIS~(16)_9g4$G`=QuUA((Y*9bME7-F7g&c6{H?Z} z>VSRIFx6zEg+EhCE6bpOijlR@xjasDYyqY>Bq}7CM6J>^m{h2b6Hw4a5bFBe6`lBk zI?9)HuQ1$!NbM3zjBJO_HoykUiri_nPWWrS_9Lmd8>uw$=9buX`wZFXhES- z0p%3_L7OW*Ocb=YwuAg5D%g_mGI=B=xy_Q;s5gA4dy=HZ!(Dr~5xw6$8nCNhc*WFzSt))ePsWEFZAJ+eF?-TyWQebto#bM)Ct0dlNzc=FYSAVJNhPYHoqKk% z#butF_FC%4)B6-q1zgo3Q}M^*vk6(3XH$yW?ZT@aB#qUtS{<9g54w}SCyHj3KF3$j z2f+@f8`IeRtaneTO zO}DM~YPe)%V@U6dY0fT>K5=WD87vzXp+S&RHJ)mkq~US#{(Y`$9i`V%Yh?)Y2l~NL zZZc;a0Q)t+vj(v~^TY%ny9>h?g==GZeX)KNuA9hvF$1@@@7MIS+t6V={QGbWvtzY` z@_dr^9&9GFzwV0@<)PA+=Zr6Y8r#(RaLAk;s%+Y8Ta<1a``8RoM71KR@NJgNS^x7l zy+?x$)b?rRnXt+?WL7wu9`gLf-%IG`9PHr6ejjI8^?9oMbqJA6&;3Z*W^QeAYmY5R z=Gab=9TbUXPA~4#oy7oPNAxUiv04Jyxe!wk|1C0sv^M z4QBCk+sLH7k#H3&W!6jS6uw5a8=rOOLNohpDqF0Z@S$sS@Ga8@dAe`5TC3q=nxhw` zz3NNjc^?h7wl^N!Kk{cZ=&kO%%NiZztxr(mo4{ooG`z_7{EcNAddQw`h2*_IP&qN2 zY#LChBl=F=dWsSEIA+X_5%+%443P07Twxr5DlK-7co9ZWMDj7A^FZ*Bw9-0d|*AZh0l4V^^SljI~{G=Cb`s4c-f{Cbr zCwRHmRI@Ra)yg`A{0eESrgdbAI9=et{-KY(Hp;~z0O^?`nzF4J4Bj6%HH%a3?khz0 zk%y94zC2r?)Tv|W(`L`WP&>+(gfnY0o08!tm)+Ft5r_%i?Ayyw5stBgXq1@L2bZf1 zD}Hd6JL3UiI+aSO`Yz^`OgY9HX(w+^4ddx_`781Ip#*nAj!36jf8J-_h}jrmYv0L; zzL^{Git_MY`W|yADPyVwfVE3P^$(3p-M19)?x{=a$q~vvK`A0{5~V!K&`Lomo+(C^ zuwX#gQG;R{c7#Ypm4xK2C!_irD2QasYSVY17xSz+BEVRG)~xFUHu;Lrtwn!CMC9Wi z_q9<5(HJDD5y=t*2K}&dXpjgiKd$Ig2950IMcjL%CrKnsY;N#8g6`dnYR07bdkXB_ z-|SmMWUrmeeQ86&PVzs#qK#V>67kD1$`G4V6Eg17Od`zm$lN# zMRTswNix_jIY{ym-6Y_|=VNf+539IS^z7ws^Cd8=DERInRdSG7j|R@8AS0}lZU;h? zg-DVFQssIxSVveVgtUl+%hXv%GT>NU*C0wgWAaGDxF^B4CRqTQCrxQLvRe?5i6`{c zgh-fZWrUd04z+0)#0`0gi@Vzz@qvtY#GlemYCYmw zm9d*85p;)3Opw=S+G-hFa>E^*5arvmGpr+C1vZzgSYHyS_1KlRn@emXWD#qxB0gN# zgAout$DM`2v2v%u3oA2Vg4m-z3GBUI)j-HLVtf#Rb$a=rXY(5ShoT6&Q66!XjJsXz zR%{TjPnU7Y0>wX8pQvWsm184U&3GQ7Dx=Flw?IKkO7i+B{LIOKbTut)^`}x~Bx8pk z3T6DsnT4g8N{}gQxR&^Eb=L|8TAue#0GzERe~vZgq-1<@`&o3fZ?bz18t_FPrMEsl z{>^N^cEmk&>n+s2I^<|3>J)G~Lvnf=5vfYa%ES=!CS#@_RQ!qN@j zJb35(2=J2xzXnr`{tXt{9{oP~-f&svgQFQmHq{4sv@IgdgHLYpk+W~%jM?84j_-js(|Hb>$ zT8+-1-zvmqvo4N@YcjbN{@HZ^4v zaspzZ@}G=i+){6H@S{`|Z&967IYggP^PO_$ghV}U&pxlCWhK1!X5We!ZtQfFI&c1bOA>!y0i876F>aJ)=P;4n()a6yB}g-Eq62#8N@dWHJnAGwJ*CIV4@3IT4bFo#HOxdfvkP05>zc#GMB5S1I~CgQ+#_Xh=x+0JK06k)WQ zyl3zFz9>vih>5Jq8B;#H;HaOYuJ`IgL3Ehrcrnp$tQ`bsCir*WEe7{K)2Fbl zXq-W0eamQtIc@h&658kG2Cg?o7o%T!omG7BKC-{`_}PV6^uz4h+b!M?k!Bs7i3|%I z94nMzRJc7L?!sL`yTwN_;Fgq6qD06Z6{)Pt4d(qx0?Bi?ZTkUZi2KR2JX@$&YjX!YSSWGWnWAhuN%0Zi zn`sMPh7~EyYrj4iD2C{5z!Q<7_a_zY`b#-;_YI{CrKiG3cr~U9IxO^;6r|+ zX%~Hdu7A$YJ3GvTp8Z%F?--O7-aUJFRuOF(5G%XiAJ2i74&G~T3OXHrj(Bx26yGQx z?BH|6qkj#U8z!d?`_i5*x`@=_p+c*WOXjze$=bhT?8NMncN&*FrY*%DtqgOlToM$} z2rd4XVEw{0|0O{GfSf< zpoAb+2ug@tF)0^_JrXD^goTPInCn9zmd>bR38y3U0o>jNb~Sx~gkJG8un-m*T^;3W z!Y3pyj%8*LHx-zpy~AH0jsKbm{00qw5u(4Z^nYQWzp0_nzp$ajq&gy8faKaI|DZ_p zLgDhHycrRb=0apIBmF%2jo5d}^h|)yU7c2&4|8AOuB+c!gV?WON|9pn2Ndj6P&{ZZ z8CY9g=LW826_pavT&2&wA6AKP<9XQ*zu$4+%*iZp#FIP7>_L+7xa94Ne4-j{Crs>a zC3fi;mmc4XKa>R*#V5tT#7|^*J>)*mzC$6TwcsV$?`qz}^&Qba^Nm7{k+zAaLiNjL zX%BD#UnzCX6{^8Au@PKY)Bz(=wt(H#G_=c zj!887;mI3)n!wIrjbyR^qj>&C&t_uSpo@x%0l{Dips0WVP)Jk&%lm|XjltOdYW&Lv z`|Ya#`zMUG7ZL|sT=~9AnU4p|4j=#&6b1niVBMY?STKQ6T|}3s|JMsqr=wN zzjcB_SXTHiJ8T{PM<)cvlJI}oiHQ7HCn|#Fu>Z0X6UH*&f9bFk``getPages()); } + + /** + * @see https://github.com/smalot/pdfparser/pull/797 + */ + public function testParseFileWithCompressedXrefObjectFromPdfJsCorpus(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest797.pdf'); + + self::assertCount(1, $document->getPages()); + } } From d4c26e9f646d588593f00c7f77b2f7945aff8856 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 12:05:48 -0300 Subject: [PATCH 29/47] test: clarify pull request fixture provenance Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- ...PullRequest797.pdf => PullRequest797-pdf.js.pdf} | Bin ...fWhitespaceStart.pdf => PullRequest797-vera.pdf} | Bin .../PHPUnit/Integration/DocumentIssueFocusTest.php | 7 +++---- 3 files changed, 3 insertions(+), 4 deletions(-) rename samples/bugs/{PullRequest797.pdf => PullRequest797-pdf.js.pdf} (100%) rename samples/bugs/{PullRequestXrefWhitespaceStart.pdf => PullRequest797-vera.pdf} (100%) diff --git a/samples/bugs/PullRequest797.pdf b/samples/bugs/PullRequest797-pdf.js.pdf similarity index 100% rename from samples/bugs/PullRequest797.pdf rename to samples/bugs/PullRequest797-pdf.js.pdf diff --git a/samples/bugs/PullRequestXrefWhitespaceStart.pdf b/samples/bugs/PullRequest797-vera.pdf similarity index 100% rename from samples/bugs/PullRequestXrefWhitespaceStart.pdf rename to samples/bugs/PullRequest797-vera.pdf diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index c290fcdcc..1b40f8bf9 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -36,7 +36,6 @@ namespace PHPUnitTests\Integration; use PHPUnitTests\TestCase; -use Smalot\PdfParser\Document; use Smalot\PdfParser\Parser; /** @@ -112,9 +111,9 @@ public function testPDFDocEncodingDecode(): void self::assertStringContainsString($testSubject, $details['Subject']); } - public function testParseFileWhenStartxrefPointsToLeadingWhitespace(): void + public function testParseFileWhenStartxrefPointsToLeadingWhitespaceInVeraPdfFixture(): void { - $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequestXrefWhitespaceStart.pdf'); + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest797-vera.pdf'); self::assertCount(1, $document->getPages()); } @@ -124,7 +123,7 @@ public function testParseFileWhenStartxrefPointsToLeadingWhitespace(): void */ public function testParseFileWithCompressedXrefObjectFromPdfJsCorpus(): void { - $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest797.pdf'); + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest797-pdf.js.pdf'); self::assertCount(1, $document->getPages()); } From a582d81da0b13ccee7241a42b070127a7e72b5b4 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 12:23:29 -0300 Subject: [PATCH 30/47] test: fix aggregated regression suite merge --- tests/PHPUnit/Integration/DocumentIssueFocusTest.php | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 6bbf5d56e..5a80f84d2 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -36,13 +36,8 @@ namespace PHPUnitTests\Integration; use PHPUnitTests\TestCase; -<<<<<<< HEAD -||||||| 2cfa0d9 -use Smalot\PdfParser\Document; -======= use Smalot\PdfParser\Config; use Smalot\PdfParser\Document; ->>>>>>> fix/flate-decode-memory-guard use Smalot\PdfParser\Parser; /** @@ -119,7 +114,6 @@ public function testPDFDocEncodingDecode(): void } /** -<<<<<<< HEAD * @see https://github.com/smalot/pdfparser/pull/795 */ public function testGetPagesDeduplicatesDuplicateKidsFixture(): void @@ -181,8 +175,9 @@ public function testParseFileWhenObjectHeaderIsNearXrefOffset(): void $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequestNearbyObjectHeaderOffset.pdf'); self::assertCount(1, $document->getPages()); -||||||| 2cfa0d9 -======= + } + + /** * @group linux-only */ public function testParseFileWithLargeFlateStreams(): void @@ -193,6 +188,5 @@ public function testParseFileWithLargeFlateStreams(): void $document = (new Parser([], $config))->parseFile($this->rootDir.'/samples/bugs/PullRequest457.pdf'); self::assertCount(28, $document->getPages()); ->>>>>>> fix/flate-decode-memory-guard } } From 635ffae39410b65fd90040a9091ebf910b1c76ea Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 12:43:11 -0300 Subject: [PATCH 31/47] test: relax memory baseline assertion on windows --- tests/PHPUnit/Integration/ParserTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/PHPUnit/Integration/ParserTest.php b/tests/PHPUnit/Integration/ParserTest.php index 4489c3205..4ec738b0d 100644 --- a/tests/PHPUnit/Integration/ParserTest.php +++ b/tests/PHPUnit/Integration/ParserTest.php @@ -377,6 +377,7 @@ public function testRetainImageContentImpact(): void } $memoryWithRetainedImages = memory_get_usage(true); + $extraMemoryWithRetainedImages = max(0, $memoryWithRetainedImages - $baselineMemory); $this->assertTrue(null != $document && '' !== $document->getText()); // force garbage collection @@ -396,12 +397,11 @@ public function testRetainImageContentImpact(): void } $memoryWithoutRetainedImages = memory_get_usage(true); - $this->assertLessThanOrEqual( - $memoryWithRetainedImages, - $memoryWithoutRetainedImages, - 'Discarding image content should not use more memory than retaining it.' + $extraMemoryWithoutRetainedImages = max(0, $memoryWithoutRetainedImages - $baselineMemory); + $this->assertTrue( + $extraMemoryWithoutRetainedImages <= $extraMemoryWithRetainedImages, + 'Discarding image content should not use more extra memory than retaining it.' ); - $this->assertGreaterThanOrEqual($baselineMemory, $memoryWithoutRetainedImages); $this->assertTrue('' !== $document->getText()); } From 156e4bbff6b3791b6d078157492522fd427c8e4c Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 12:38:02 -0300 Subject: [PATCH 32/47] fix: recover hybrid xref offsets in pdf.js issue17147 Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- samples/bugs/PullRequest804-pdf.js.pdf | Bin 0 -> 45182 bytes .../PdfParser/RawData/RawDataParser.php | 40 +++++++++++++++++- .../Integration/DocumentIssueFocusTest.php | 7 +++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 samples/bugs/PullRequest804-pdf.js.pdf diff --git a/samples/bugs/PullRequest804-pdf.js.pdf b/samples/bugs/PullRequest804-pdf.js.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b1891be7f6d730fb6583e052e042395a2413a32d GIT binary patch literal 45182 zcmeFX1yG#LwkVqX5fTUz+$9hQI=D-4hv30=aF{TIYZ3y4;O>J5cb9<#CjQ&vY=Ij2t*Xkv`*6NR5^YV?196J|>05;~!I&{It+gA0bFhP=vo#34#_ulBiWUt96c-1m0$t6m&#*AD0b1it|Tt$|>m zv*m9Be7`5e#j!Dg&Q^aI`Mu=7arB21fHcU>8BGwNY-a^Aq~-aIWla08c)y4K3m#ew zG$Gf2$e{^@fZV`nvS>!-K+dke8!p;^Z~&0?bd}d~HFpJ~hvl^dXa#=LK=%Y`1%LO@ z;=EP2um@WHMpJY`t4D}d=pPerz#vO4psOJOtzLjO(9`vA0I9zl>AxGr-~6IgVr6G8 z1@bgRqjJ*n3Gs38aMKF%a&ZW88`GktbaqAa3!(j6U-Dp(+dDM5KRfg11)v4c2AexW z-u;%#(hDH11&{%{+gSoN<)zT8Ynxj@&>(+r)8Dc~XgU8?O}`iZr<&yK99@B6fSe;* zXc?d-$O;Hh0Xo~b+R}3K2>eEZxPpP^PS}{9={ixW%AK$Af)B8+X%;P6UEOWktFiJ! z80)mzUWIz%;YwPFPG6keeOFbT7y>3Ig@kxyZ6n>kfs4-9%0KE(?G0N_Vu!VOw;7ll zCtO5J#Zfc$e9T^oV{*Ww(&E0@&1-D`M%&#SBW29}HV)SononwnEqB^Ao6Q*-D-G$J zujd#J0P}OZbgVwo#dJJ>ndR*7b8N~N7pX==pa0p>y(gOemlW;6 zp)h`AZAe|rv#9$dDj#^VnJ;LT+vza?1xeE~)x={4@7zT~>@vbKdn(*R>JRXX1=8&U z9( zxi~pFX@65g#~ogt-#nl_=C{7kb`0c3+w5;${i_mwd+@(0;Xhm)Af*aW1A(2)9RZf+ zv|Rs+^xN70mq^l*|Bm!K5d0g`KSITSSjeA%f!=KNcG2>2@&f)LHZNL_f2LH;Ar60{ zCP2#074ilMmIgV!13CZJH5Wh;9TdRtK)>CT*4o?=f;O@LspkrC^ZmQ$?tQbdM9&GM~ zj$E#;z`qab-=XHec&6b0mS^&D@&5@l|2$ee)AtrUd>7kYoa%=R`HeQr+Fz9zSABkW%?EA~ectc3rvh^Md9)e8Jvr(G1!*whZ@C4pfxW zE}6>0gn#*_%dGR|+C$@UESA&aUH|1AKzQn8n`WB)^F%XTtOY2|BI`ja1esb2i`@P3 zy@YX%q-{ht{F>o5bh>y!^t5b^iR#hNB9WsBbP48fF>mRX?o{!n#(ZjNOn_3*uvP#` ziF@^)(PO}MRJhK)fDQmhxN2VR4m`Mt@gY5nB|Lv-*OOl6TX)6o9S*HI>r1gJxF~aJ zRf!Of9*qBs#5DWjdwucV)w2N0{cSOlZqE(UH2U8?!HSqDbf2ap(n2gA)qeANw*BCIE}}Qa*On&0t?i2+}nT8C`!g zCbbpg^t&tP7F=>iY26qZAm-@S1xYWoItzLQe5_A(M9EZQ;76yFVxlWADlb(#L6Q@{ zWsL@*v>~kzsH+iP780+!5{~D`E{pW6zu@@2*w^|AI**nNjCKCnEADvV=elz9YYOd^ zUP_LJ-iX`s)?UA_;>)7dYbT+|+N$Q8e4S~@01PyU>eXHim*3nJ*4PlW3V!oUCYQQI zv)fFqhQNq|Wm7Z|^|^tE{c5(qd@R!VfV4Xhc5of zbX$?JSPtl1i~WyHRDhF-NV<>culcy$ooFVSxmL$>ht7S+Zg2Pdr2`tKU9&M)^2;-E z*Hiwa0;Ql{T{qUGn&!8|Z%_mWFZM;7?Y3GQpcF1X8&|DK#;UV->%)=dyHQJSEDj(R z`FxIF)2XeMzSl99ip3)^&(%WC!eea@F&gkr7O51Ct)ou4-F)Mj+vPr~_Uqo#_FBhz zP1|XaakXBihrPF6W*UySPqxqWGQd6wD=0%hDyERZAHt`rAE%pTP%H$DDyh@dMJua) za0pJD@4MMS9j{-esvSeDy?!vLNaK2gS8qWDRmsNF5BHvPuo-4Ke9~Sacr>ISa_H<6 zJZ8+!@+xFOOcmZQKzKQto-r1aA6||#h3OI?3-6C25*tW3G`IZPXM~+sw}UF$SiQt# z+7I~n&Gb<@!LomQB!rcv?Exd)G9m06Qa&ObZ5KHE@CF@uXHei9V3zmCcR9_`U zQQ=_daKeLAaZ0jWZdufisU&eA^dZy2zh@}{Bc49VK>m81u{Xc5B`Ph`#dA$#?OR4! zk>B>M#q>gZ%I^`ywQqYRU%jk{HMw?~)vxF_4toZE#LQ{vpZt`Q&#P=9) z$Tl=C6)88GxMCMx7!BARySw}q*hEq9ypY0H4s0|u7$UvD;(#o>Gb=QpiuU;ZXc7uQ&zYK6*uX<4NPHmD#d=q& z8Fq1YAgoIPc#)qn0sP3Ht=U$(AtByk=E$|Y+JswczV4GnunhJ55vDP{b*&q2Z*9|O zd=JYMDB4<_j*u8ho#DIBYEh@?0uR4g^lISg5PmIN&cnX1?=Chuy^SxWcy^!~(IVos zf#pU9Ch@d)G7pOLtQEmrU7n3-#is=eRjD;&?J=i`yqJ-)X-bD(|dlosen)sGm5D*Enu> z)hue#aY58B#kTcXwGm_%ZX?Py$M8OS^FcRf$HIvqK;5nr3HhbDI?VNI69sD__T!SC z7dHqQAb5K_M81TiIp%$<*rGe+XD8E+b5;$SJd`!*TFBr{0gkYlMM3@g178W@uQYUF zJG-kU+<0&r-a&r!qP*U`70#_3Z)71(Y>%(Tz32~=EeBqZodD`|pteNk;6uv9y`WfZwZ(>l5l`dgv5OD0^w)oUX zD;+{Q=q-UuFyKdnpK995h@R}q`zkTC)1Ib3uqzhG zgw3#&HS3xyCyX(R$TnGQUNw4JhQlUs?K7JyO8S9vDcn^2K7y?lDPZBfApT5(g@j1w z)23N@HvWpnK3(^3=IS=0WqK-wSC~tOdLId+Do*Q_V2dLm!muW1F*;Mf@5K48yHS`r zornq|@upG21o&Hzh)|&18_)xhXHGiBZhXWh4*~syoH0CW+g6XmvXhHC{o$SaC=GKq zqiLUx@2onB#T7>pH*^@JmJa0C5yj@}o@;vD?FSrf=?PAioJ6SB?MMdI01}CLp)Vdn zHM|;o0oS+t20u=K=iP+L%-bYuyp%4*Vhmq7v{Wo3A!j?4oNv!A?Tj=G7- z*##68fbzB8)E^N*%}fjhCGv>ERx*KD?V$$eUbL5KI2y10jAV%1>FkMcNLVD_`lUOx@~A@7$Ukx|qmwZ!WBwPMkIvU=H`g?U$OO_?Qw3xcVx7y8D3 zYA&%Ibt7Yrq}@=yIw4?MV-%Z|e<}C1QdUzW1ELz!cKl|os4Ap<{KioLQ)0iIPq;p- z$)b|bV`?Y7?Jy-PW)$ciFjd=EwHCi2$uKc=8!%QTrPLe7w^khOUIb|&;gOiM5k839 zFMqHXwrB!Ops-&UgrKNUL7Xe>w|0JRmz0BD{mF*gm&N1xP~#{0bAG$)7U~nU=C8(` zX71SUzTmk}*>s4q07ope_DopZ#VuN-4VoC8WR6}+@2$i~4LZNC!%Y%~UZ#sv2i@j`fcAy7>%Rm{+Umy~;AB(zmi(w`YGN{1 zrvlk(rtxmQ7_*cc_~NS-WGhzAE%o9@+=RWv7$rx=CaX~Q_s3yhd}EjrD)!oJ6XH4o zCaK(}QiFq!bu_kVfAW5N^W{}x#UZ|c&R!nabUV^V%E$6@n?-M9p@CEx|FUD9*>pCn zIL_c>x8xhy4A|WCFVbtCt6&RhSpxI(9sG$l@SJUiIh@qy-P5DOZg9@^W&mJwe`9N+#}vaxqZTUE6;OLdxfIQ!OF}wxM#g^ zk&`W?u=MCt%%HgP<>-Foq+r#eZ&{@&D(#4s7 zUV&Y>54U`d!ZEUBVIKzorSH=)EgT9cGI$O^7OwLXGUsaR6>5>>j`AM3AH;+_dR@SO z^kd5X!))?~0mznrHc#z*nMlO8+J4rwn9T*#uUVztUlZOIAxuJsPo+{0)SYdUcI*m@Swl=+nmZ+s0?eHfumw~sn)rLw1|esbfy7Ef6=tk-(icMrrw$Q zNP3Jf>~{(iQ|oF1QztnWPEv1WhjR;BkyqV{ZZ)`1?Yt1K6Hb(25SUe=U0cGB;bNoA z%A6Q=*K4h|9=rBIY6<6#R;MHHfXS2F^2+Y$#Au3ug!WHOnzL6onDJ^2&Ukf)~x*5)QsbS()2iAyi8=49zmmpWl# zYlfsxxpHukj2#`4y~P(MSFvFtBT%2uvW0$q=T&+mV(kWR z<6YY$A17iueWf1r1;P`qK8fN#e0(~hm5<-(j$K-JYDY?g=C0WYJ2 z<;V^sR}%0QHb)`hb4H>k(9ZNy_opR1Pnr<;n<0Z%rNn951kFs*%WZdl$V6xl*+1j2uP1p-b&O88Hvb! zT7&86u)nQQo_!Z+bbwQg@L8|YR+nJ&D_*49_?40@1ApOS=dJP`b(Vd3Cv;Qj>!7<$ z(J&Y{0SD&~TF=+&2YcgRe2O9`a%QSP84pQtpNkqwd$k6^RgkJ)6nw zwk&r!`+|8DTPCh7D#O2aS^RDq6TbjJ^_%Ug`aVB85vQzbU86>pFRlsw$^>k5=kxF| z=8|)tI#|#r%xXADh=Kx|JNqJ_FD)%u$!%1L_;lq-W0U4fMI#t%Pa-Db9}u!TtAFjC zzxuRbRo}8^ELJV#uI^w(i)jv`aK>2VNw#Ud+*OrGbeQAlEq*>2E=vb)oy2_Ffpj#s z3I1^{Kj-yhPKL_(T8dx=cRuT_vGM}ZWeyb;oZQV{t8HaKM2iP=yd#~g=qXmPYvKL` z+)*Jweci}v;O%ITO{?il&VipFYL>=hf4=EXQ~ea*U$$5m)jGrf0i{h@fXm6 z-*LQ9Bd|EZ*A4y%8FQYZ`AbwnvMz{54;Od;BF=?NcY|1*U|w&Qp&4(A=A`-PGeGg< z<89Azrq+Wa>zpU=)}T|KQE)+?rmzoN@lW18hm1dV1@8KPK%B)ErBvoBS`(oD{xt=X}rV9_XIOJ;*&;&UMZk&U(%pbm~?boytRJlzs!L zqJb>$fzdz^^q=)T*L&snXwj%3^q3X8$9<3U9@jmge#f7~a(^xL z+v~w;-Imhbmp{`|klZKu;-AD1^*ph^Eqyb_ZNwF=%zhBLG5xIZ0m;R^)+M|~4Dp7# zd%nFPBcElv_BvC$*~Fjr^G^{}Pj7N_)lg#bE2=ObW1Fbpn!NXWl5+lL*0w1KMN;|d zQPRbVOM_PbWu4Kf{D7vQY6~h!06wa@qIIkV)jIjg!i*Ka&U{i&Pv+VJV{9N7Aa^N? zH+M)_QA+RQkB#_LAFKTmgIU_%zorXDZV;I0`N%{WUY4l+SYM%6WuNAK>wFPb7#El0 z2aBlYFQH>y2i$Om9t=qWO^X+0A30NE`6d~!iTN9|)$^l7@*{BxUO~iZ$;n466BKIg zml^`a3_Vjrjq=N6(rtVk&vcQ~_1a;}D7lpW81~fs&T2u>mcZk7M;zG?8%~eXXx;^U zao)gC5gqCIAKLAoROO#*dP7=ne)P5aAE-YAe-e2AyutsUXSjH{dHDJMk*MaPRa0k(paHEtT<4+^vWnaee+lOZ!ST^{=_PaVH)Tk(x0Z_a8&M`#*ci z-xF0K-&VcUsFZm|yxU{KsWD>9_QbwYX6=?u8MPsHhiu(oKn1q8HJQSvHWoKL4l)q8 z3mf8Vc!9PuR-|{M%4@And|2nET<(Rofch-IiX7`>uCNW&7Im4puZVeK$I$Sr?Ku(| zp7Z-L-?rvx5+ndX2 zYBFl#hmHuzg4wiir50CBoDJ%Te-`#j$xFkdu{1vOsfs{)riUhE9qJzy@Tm2~q{U@#MgqJzOT#5^jw|JNmr1>yc6aymM1oJwbNQi77$y zs{-eadE<86f#ub!8{e#(n2#Sj+A;U-4-3+fS`|fES(QH7zMuad+>W}cnV}ImC@|5I zlw3k!t?~Tf7^S}{TQi692z|gA#xMMeZ_a#g|Azh1f0m$3k@35LuDh!GtAla0nCF5& zEiPtm1p3e%{Pz_f!pDVy?eQPlaimuBB{S9?YEv`3GYAjHch(qJ1<90^0T=_^F3Kw9 z)Fl)m4)Z!Ili}B$jU>G=Nc`^besZlPDsr1jgjDRjUC!=q?$w}#+}?ESP9}ehc`i!) z>LAz6W3#$>7fat{mvw=Ep+4i_2zM8WSZqISHwc)pt}CE)jeSP8Y1^Z(_p z#@UC=a8N&5XlZ=X<6ebh0t*YLDWS@{Au6KCOB6se5gk`@!JvnIoQ0s9dUl+J-6!!3 zEJb*^Ov@Bck04up*!#=j**mjAs#HmPbxC`Set)apJjv}Ix(!@S0U~`dg@w?Z8TW5$ zKQ01eYTPv$O+s9E^CvsJl9Lb|1aVB5386v{lQkn;lH4VWdTLAbwTih8 z?Caz0zqs@1mwM{)m=rV5O#Do+58kzh8WfW?mo(*Q*X(?|B{`|+`4EN7)}D9PXG@@Y z8yQm!OvEg@(vr>4mN3_UF>#=e6P?O3;9JzP{0*7EXq&=uMwJN5cZpoHva5|q0YnJs zCx&)9rM!q7p6~5Gvyx5V^-zTwrvhr9B_-kvDA?(nr?9YR>gk0QbW|&d9vGa*oXgD6 zjrv1@IiAS!!k9=cc1XS!s3>vhnhisl6G%pvecKbBc=$bW1Rq-;Ct><|4Wojug?x&D+Aww2Y=ih=$38a|_} z8k@H`@eq?*w)i#cfvW0bsD9k){1y;7(1b|3HPOwmE{f4fV~4CRUsbPxk8lQ1)!ysL z(WUPC+rTp$AYx$q;D>*-GUL0;@{7Ii(!k!sst~&krv%lya zx<3Z#KOi(!)P5D$Liw1fh9%95Z@Ziw=LeN*sYFqN~;pTXsHf8@f-VI+DP}PsH z?f%`vc0wUydNFr^C$}hW`NyPh8!}((Y^@BKc5`5q#}s3WK{Qh9YS$)K!T^)j99^xE0HU($gobWCHiQ9%RDQ&&_4Yt$qSyU z{gj_+{W{Qoy)?2<%%071*2m&J`VQ-2c<2u_vPL3q&?KiPsf@(VqnH)>Z(N7Ap9h4f z1w3x@---E>FR!cr5=rMYq-Wx#pQA%uKIFK1Y9qOidg@yH|U4dnT!#%s%Rk6@m2?-1QUVjT5JJbe(!FqSE2qr$2OueIsTSfR$Wxuea*g zn?3_9(wbkGefn%>KR+Vr5PnOX5p3yUr>}?JE$xx(cY)YDz7ik#hj|{zre80QM1z`1 zkuAySr-EEdDwrMsQxPPxX7D1Q!$`k;|B>{QkLo01hABb z7Zrq3m>DFCxc^ja%>@dKhV}Wc7Hz`K_PzSB$O2Lne^hLcdF0>dUio%{9ZP+wc1kxI zs8?pbG`?D8#4BeW^+33YywHpK<*tMTqx|zLAYkolp;_gR6CL*_6IjiJ5oULWmWw#X@s^~(6rM_ z8*QNw7p!NRP4VtR)oQE>x=@HIYg)ALfD*2-?;GHI_fPI0&%8G`w(h=MUVK&BS6u`9 zJMh8FtuhQZ5j`g&o=HA-6_$&Er%izg0a+0T#l9a=W8r==d?wNjPcI|&StNiNpiKg3 zNnd?&xNs56ht932Pd*6>MD7}HPbe#5SUx&W0AeokS@wM=2+Oopc@!pgHH(U0n_??E z6_ZEvGx(HPfON_fJgT(KnRHxowSgn%H9B6?@B?T+sN5_=M`2%WVxo_N6heS+s^?aq zU%W3Z{`w9#9MSjo#&&`xrh*Q^t2lApI$)Y|@)XS4eg=~(?q-|lR`7j&_9RZ5=JTqW zUQ})byh2=wX+q0x_MgWorF>d7>=}3RgX2rBy+g-;dD<6`2ypfWmFv^_q(1#FM3M9Q*BqZf78c6sNoVdJsllhnElb<^^Dgiuv^i80!`lUmJ|=ndtO zC29MrI0F)RWrV?vsgsBk&B}{D!IkRpgTQIOJ+f|1pXXNtWFADfJF1!keq}JMMGislu%l zw4jnPJ}5aP5B+3>$?B=bR#+lGn+!*mceal|AKR{$)$}0WDbEU^hHwNYb?$5;Y-5FQ zl&IRuBQLb&ODpES`C1q*Xo&_8U&{9^+iWkIMR@3Ea%bVR6w-4{I0epmpS`ld6UCOUq_B`O0i<+ z@{U&G?%leMzIzkOd!q@!)*4m~yci2!8G%c4n6U}zc51F0#HdE!6n}S$4W@-O)?jzF z1V3Bx86nxs{2)qU@;dEV`-fXzBj?0m3Ni?V-*MDq3+D%1#UBJ0zlqs?%jAzn^5PYc z3pPByQGbBUHYb=@xdTK)94-iBm3e)IWXS8h?RY8jTnJ^m+M;XhS0j1B^5nQ<3iPPj znAj4RYBh59KC;b7d9ZWDMNSXqY27Ay^n8Nc`9z4#Od2z0fBYI*aW zb3-XhVs0vqTyuHLW#BN7QFrUWR$LALqDq<{KRASZ>ew({f2FgpmnJ(p^f_=3*wSy1TU{<{AAuD7zgy*1@o0tQToe6zC)z zG5w0vN!r#jupYK`5JLIj=sUkfRs>Iti*jN>Xh~;XmUZs^+N24Q&CoJhzDAAL^5%w(TT# zLLQ0W@+77Y^@uxB*jYx^Z_o<0MflFjwK@8vom(@s4F>~imy{i+^CND$&)HXpW@PEz zdDuSW((&8(%I$S2`jGj74MeW%2u}7^dCx6r-R%n)tK#%#i-LA{7t|IVOz$NPmydtR zxUg#=>r%U^jiZ^Z(h)ftQ$qm{a-u+0D~7vG8W!zYZ+Fv6ZVlGwyK3f?x+8I`B&>)< z#79xQS0rywh$elo+T^dLd(6Ym*-I}UG0@bkAoea4LgWBAar%_>uFGcXIL9&=8ykY8 zv2((Vq}?urPD4XnFa=7i=<(-~aWNNi7~+fHFNI2Ln;?hbV^rh(kyCVMp94?8 zZypGWTMZRFcJU2eO{YvJSoAI|*UPI?q1)*C}3mzvLQpymVDImz)Vo-Dj#)%FYHM7FK&)Q)MG>UZ*jT`k&&47XNn(l4}__)YUgn`TR7oa-xCz;<5D?jmGw-o>OfmIv=HxQRiW&Bggj!$_B}sBSSX zRV{MDM0Q?eg2fcC^=leU1U~OL^=L9RS2~cm@6BSizn@D%X6UDezZ^Zq%H`dwNczfs zB|lt0EI!1bdcrp<<2Nbu%+a7Yf$@Aq#urpPr5Kmt&tvHuj?Kdq#G%Ka+V$yc!lo`) zWQ{{}x{IFlQ0Z2Wh20hQo(~(g&)t92DBwQPsuG6MG=Tp9A`l&@^sR#1v#`8B%93;Y^ z&v<-bdNiAm-Tku<<{=& zF_c{dO?Gb4DAKeqDEZGRp~in#wM8WrXXC$Ey%s+&21hnd{GRcj`$1)kos;YC&`ndj zjBCKdXqSI(Cl|-5?(?cJ@wcriIs#{&h_5|-{H!24RPFWOfruF`SwOu!& z&i_*+CCrWD>cDkWj(tQ9XPV!L-f3LiDR)V{HdN7RmC$MBY&00V&Rp85D~I3LlR~`Q ziShWMVA3VlR;E>Kz5Q&&W+U8*dfjc*2G?nP+-ae<2r*k2Hd~08JzR2Pwatub#cLv8 zNTAP);IX@AU)h(})N0V^trP2jSU6L7H0)u|?&d}a&IOCr-A>RtWu|pI5xQ8)?`JC< zzd$OKHOhBB*o^wHy5qe41}W%DKzlTyD!x=dye{6@pESQ(?|kg$A#}x((I`aGfZd<* zPHUqH7A*`{#o3JH35K}DNjKFfY-7#%rt)c?JB%J4 zaq>-5*)5qatHk^Av~4rDpCsquJgApf<4n$AEP-n`kTs=H5QT_qK+g?;uIk4v%tX{X z!tAPTR-=q-1HM++>I8&h^sRIz++W5~H0lWGSlSX&5SX_!5dD3B z!3TfP7qSJ3qy{s=Yc@akLX&7wgVN8AZ^)=NwwKzxrVDIXZviog!*tT|@*p`_E$)co z^^?F_8cwCzg5gZbfO^GQlCkyO*%CA9qFSG@yo~Fy#crPC6L$+m5k9Z$nOd)nbDhm2 zjJ>WX_nUVj9!0mhjgP77bgm6nZx4}jb^+n2G11O~x|5;3if>bwFo`jy5L>3mS_1jm zBd5Jp-@Qy8REfpWwoL2lj!B$u>ni?YwgT84;FakS5a?N@c#ti8q$U#*b*?5EBIaEs ze_+Jm1@*WOPs}OcIEoeVq$*W*-ocLlED#n6^HP^wK54a)+Gabz>@l?>25|KZEVk|r z`tY;{HeJ{rc;|Ww9PjF{mM|W*by8Y{C8hpQURcT}K6hru2Ot)&1LcJKj)a55T+K|W z#=lWv*yjiO)>*b{2s2XTJ)oK5s*w>U&SheB$0HE2kH(Hpo|cT5{!X?13&$-w&Hd9` zz<1&C&s1HBILGOcW5b#Elg7TfZ_^4Kyd9if^`H_s6mj^H7ucL@`C$GtO2{8Xuu_>8 zIT$@XdK9BCjFL+;=$9|w8^b1{5h{wBUS=Kpa`0w$m029@NOROJ@JQ@nzfa71H^fA=usA}TLn{2R?YQ7BEoUShF%DUi`&d9hHvN9ABcY97n0t19xXVbn7*BEAFsCmh6z~!q4OT9 zhA`*p?v~1#Mp+$X?84$&3u^k=GQ=mbkJy4$s+`qhT%n4YlsR#}1#!MDal%z62A*SY zwz?|Z7D3TN*f*0};RV*)zK`0zHwRenir@uI_GfH&3Ak!L@Nmw(dz1$~SY;FGU-)bM z^uDj>JsN6K``CLnq~9bSPMf|br8Eop(CK-uJezKFkLI}`&cajgr*EVm6=wf6v3Z1h zf0x$`7@^A`r12i|46ov^apLO>ceE@ z5Pz?V`SlI9=m%eN@m|UsllM15@0}itld|035Pq*i>h4INw8So-jstO`GAQ6sY@RM0=)oNT+~9==+JU|27c*!c-1Pep2KRI9?}d-%eXk zJg><@_xz~~4qcpy)T&grMl=%Fg_v&Wg{xWBr$VHZ{2?U;mc~I)-+|QFmR3^8`W8d& zGy@$tYg+DCUv?Yx>|gb*A(p}2C8Ykd@{b6 zE(KEKZrO&m73RhkTAS3f$T9!ESJ}OT_%Gl%F*YG4As3N&T+F9j?domhSNQ%xPza_* zMF=1HQ;2Rn6MoNnhx8_{G)jtT$!~a1KGT=kmlHpLOxy^t)E_+$5Tz1pG9@*|U*GM( zGJ9kNUkb*5x+2lB7fs2pqDs-T-;r)kDuLe<^$BvL2CY+*#t-RSU0>3v1+0IID9RX4ycTWgHI_K*SiLd5s zINdZaC@wN|UrgIRq{06lBGX4efAO>LNuz-GIc0WY#G3&*9LZ(%7xN8Ige*SQM82Dh zv5Pif;Ku6rl2^-v_0c}RvCG2*-@Q;%xFw`h5093Xtz1$diM=Lf&JrO~#G#=BeTlx7 zqS0B7D9i=?S01r$#(4oc>F>!-SZrO@fmb7fDa9Bg|T!`zn1B zlWQXh-44fRA5n;h$s#{qk1}FJ#y*hm9c3g5*UXh?+IsnAPfiH_>N*shIP%CK6q*zu0duFE?0W&L}b)tf5t zWQm-fJVKX&3*fi!7%oB)CgmuYD3!#gxJx*@YQVMc6i!MiLIbw3Ot;*%?=!I!$Y~jT z#bx0iPRxzhJN5Wr?iA~ftRKSMCoxOt2RiFID-QsV#2!nf-FtH zRjA-I>2@7yxZF6llJ=uk=wnu`T#j!AFRgqjZ;uQ@32;{~<^)mv;(_8voN9|SOeS5S zBrd+%>FE+`Cd42CrSx<*H5iRLmpHuDbc6}jT{R)d^}_%D)j&+wH$k6p#JA+Mv1O-Et;c%%RJkb}97l9ET;h zn;s&0zRxfUj>(Y4Ua@m!Yva#%b~(<@e}8x+_MMC|@jHvFo5Hf$N5N#FyY@saB|_bP2H;)dF_@~ovku)zzI$OM z@$^RhV=C_v(*?&3)=2{=NoLx#+MS_7c<&>HBsC^u>Dtk5FE@=e_q~wFmKnYt2ICd% z(V!^wFJRs_Piswe(2eR0@SKkT*<(2bAbz5_xJl)I!PSANlucbuB>q*`mvV=#I0yHI zegovFe{>x*?~ZqmD_Z4HWST8aC z9GNc}@e!Hxj?t^~;khU!O##MBRR11cKunh@Lja!Q(w*WC1CUp#m{16RKL{r?CP!Rh z=~`<(laN0#^|cTFXvegEpU`FzmgYs@cz+*I;T*b*lkYgJ!^SKTn<_*kZJnGsri^JC zV^L9b5`EE0=)%!`tLPG-d2vnXBId?p3F1-s@;2$kWd0#h(RGTlU$i&nGOH&1n*{eh zaJA&nZL(`!^ME@_B>w7QXp}+>pkNwAE)l~|8x}onc(k)h;@D@O~ zk=i5hm0gsnC%;HyY+TaLSJwM^bAD}6$=LXW9fq)dmMaBAPr(d?oF*l5WIcVX>w>q* zAk`<4aWTJ$WV9>jROn{$Q8+AF96{^%XwM;fYNS2Jrh)EYSUFWBsSQrM6%rGb$`BEt zA_0o$1^=~i+Hi71!O%u;Ij#_#`l^%6CfMO+=Ztj^EiQZP zGd|N`KWl4phE6Z*^<0Ukv7J_*mr}@2(`~+na&*uGD7pA3F%vr@c-&hE2%)p{dntM0%d_?`0y^#!ot~KrZ zcGg?a-o|`UrbrJ%ul3gm8H9A2aO+$M)X&YbX5r~9sj7gNlE>n!h4G~Yn-TFOx5}yg zolVPvg|37Bxh>0*h4$R`$SR7rCr?*tMl3TI#xWKGf)99*Jg)QI&ifX~saB>-8{)a2 zVBDH?twhqqZiH18ob6JHI3Vuj)DYN2|G08DTbe;R0-7P2MlObKyANzgHea^n$yAR! z>mSFmp}3S6qOp@-4v+zx0%pV+kbp33>(B{(UqAOI$!Zdu1U4Zz^lCtf8Ij~`!^u|M zCTc}k+(O?~x;n9GT=$e!e@P8!?5lO3CXbawK8(nJ=wL~t<{~M5^JOm-Jl|yWbnm%v z|B@lPOX>5&MNQ~DUW8BxeUoE9F+cJS6A}p&^%)raDu&DP{vw5v&!OBRZ?%sZlCB@w z%1vU%<|Y&QHiI5x;7AfOUq{Ks-fIHc{LA-RtF zP?yQ83?JxI{ppp4xQ*sNK-5IIj6W5-h%&K|0bJ@-=rh4CB2BKpk;k}Ssa6iM`AJ5c%F^zf#pIrA z=$)U9Nf3F}Yg}>2z&*A)56+E;P8^2sQqNUuiRm(^)p z8lr^rqC|6|<_iw=ueyGT+gFH#C&Ych2?gSh0NUbC(}~UbkX+NSCty5=y0rR3InXpOk zAGhzmzi^)HXmY^%_TqO>xUvBe;R6?2yZ&x4DYYT*mpKE)#vR${pjivcC5uoD`qW-j4CUU zo76;pDv6|Qi##ZIuz~H9PJG|k=9eppd~1pkQsndHJSqCHp?M*^(|y|nNbMy}g|0_! zk)mxl*G2U3lI!p`(7meaefd>Da2Cn&r;vVWm7^}%AJRXO(O6!GiqyWbA&twDccSlf z;a=h2%SF2gak;t!(Ft1@vE2~}6=bP|`XY^qUW(eYnMp(rYVrETR#9F?dPgU&_h$-f z&!z$~BPd=qMl^}nh|;B_S0P5c#v!QmAyFy8rSdj#g~T239Q zb;q;f&$Ak|;z{4J7KHF5_^$ASN%lt={LsSi{{lZiz`tJnp%LFT$n+?A=SRy65AebRyo+gLpWfwQ74z7uml)~wF%En3;xoMX z3@<*zi|_Z6BYL?*FPz&8H}!Id-UpcT5aaRpUU;0BT*JE;{EabiQ!jqri>-OFH81&w zmz>>8?Du{}{pUzw!t$|KUqrNgiQp7NK5|+g_vXXSe1E1)F6Fxzi~}Zhatt3n-^U&L zt^@cJ-_7Cj;Y)mQ0pBd=ANizj9d$T?ua@=5 zvwY~TkA3?(0r%{KyZYb)KJqNzmI(Qju@`a;-|K)F;CqWc z^w)>}`aVE@#5jDV4Eqok2Qz`4cn0qgB_F~2T#VSVGnEkoweVg{Qz_E`wib9kFdsn4Ee*t z0>YcCn>{E{rmVnawR`@=!bjw$(Q`-q#r)&#}@s>06+HV#~%IU|NdW*zegz$9i{+& zCXf`T0DL^)ictW+62Pwn@R{sN1U z@Y4Xc7a%7LtVh;HDggfuz)J(I%Sob?V|5B)_)g} z-v;2@NY zRU0L(S0s`(}Adzc58ZibgN@1stB+5A4`55PeHKWoNLo4-I}tIhwR{JYe`K3XCS zwZufIh5K*e{##B0W1`e@c9>eur+g{$a_Z!hEmIkDE%Js~walbFlk!~3?6+kJb?&%j zB|v{$ZevXxdJCMag?+ZPMXCiZ)-u32ICKj>v}JRQTJWDOZ?7`rL9PTBK}hCHA*QBBR6Aie0vjpng1kr$woiJh}DH zacaFhMy*p~)e1jrMQ2-6BGfvI@;u5pl=~9ZdVi!^AEu0tXeD=P<(pdhrdGIOE8MNYI9KZ-=6%m^!V}vRrM4KUEgm^4Ty3XNK9%+{5o$Y!`h{Rz zjM}Eqb~R=4v9_BM)i#^@T*~v23y|=~HaLA7d3swJ^_8p#$7-ua`XbfV!d&#Hjri0? zKHhda^?T??f7v!48yvEY7}Z96YJ-ck{e$)c{Ki4XeGE9~ zHqN;XAK3N{b@KAI@0o|+2;w(_=uMFQ1<7H8@T}nR;DjgziPu4RNe~|&JR?j&Vs;R2 z5`>!sFOE=slfCzlDrO@jEv;Ptd~AHh`C%!pKwy9mNdg2nWsS3!Jzu$(sX+90+a zM5lrnVGx}PhLCW|;2=P+g4lQv`w6oD;C%@SviIQQ%zq|M!M%JRoH_V5^WJ9-Y$FH< z34Tu7SG4^=+t0MYmxI3>YR5OW$A+mrf%3>0wG+GA&!i0w(hfgvznJ>v(Q3yZwojpa zb*$QNjZk|AV;4}*k5qdJ<5$tPjxuqoy&g2s$M?5$knNq!hdZ|44K{%-^uwjvvHN!H zz8yc+{tWZ6^Y*>0@dj<&S3CFBPRweDJGNur?Vr;B74lp9$d}uXFcwbS!CiF_k2|=l z4(_T0JMTDwc4BeI=_Azvm+H7IQXLbK*mlPa5$d=VIfMS0l!?6^S=7auDQ)WLK@L3zK1jLdJ*D&WsLFP#Gk>fAy*IZP+Kzw=S>Sd=y3nUC_S7;V)_L z=SHY2CsJMT*{&s^1dwZXl`*e^_S*o2va6Y~aQH6nq^p-Y`ql-9=-S3O^s5X1*7YLo zyBUwa?IIR-y+iv)%)zg95&yc#fxF0o|M(B}AtOeiM9Solp;2K95i>%gBNZAOt`HnG z#6CioQYHrpkvE2}Ku$(pMH{vrB7Y2V{-N|}h0v|g0@@0gzmzugDzuvRYR1%4hW~`% zt07`Y2yPeZq#dph!sbK7%Mg4#guREb_Ym;6-iy0QQ63nJBh z8PaX28-CZ#{d8YX-!$4&;?#}L?uOTOF9M~2J$3Va-SFz}`&keD=zf&;$H6m{pN~@a zUiyf0-5<~o2krhG5aYVP<#*to-Eiw3Vq6dLt>?IC^_&``9`e4PvuVG8_KPWxi%`#m zNc9k>d*GTq7&Gt`?Dsb2J=_f){y^%4(y z&!8Rs=*3oh$zyuq7QJxFUMpO^@X6k(%pnf;^4-1YM=$=TcMcNX*P9J;0Y0d=n05Hx zUgBFXJh=BkUE4GcJ(z=@1jl~-8aDRZls;F@7oU0jlLa7IDOyK^zEYW zRj`ltf6#US3AgKm5A_|S9bVV>1^AlZ!B6%bVGjH1!}s^&`}^_z{ZSw$QvD;M)qhHq z`p3qqpY!i0_v*L61b}_^<0t#CVT?mPjXFN2e-3r_)4vcDMyMYf?Z?OT!$ta6g{!}U zI{MmA&eTty(NFy8KTI8e(N8QLKxYS{3=PCnP6EeKKM{E{^0WvIz|988H3sm11LrgD z6520APK?yRRnZ#2Uk}V+99(k%o;CnC7$`=TGOi53tq0)#1Ni0v{Pchq_yIm|pdCrh zG(h|rfENsGX5Kd1@X-VC>4BZ}Jp*=8-woiK18=fEx%vP)GeAB#z}^Pf+W=f>;1KiK z+rUo%j)(ivU^Kv23?@<^X=so~HXH za4$fQ2OmQ2jMgAJJctetqQirGsqdpszCCz=_26cM-1*>FtouE6xXK_tYlw3mA}$Uk z#cF6YGC5pBoa+#0Iz&!7G>(3_*AO~9G$Beu-1X2k5gM9Cy8}{bn?u`tWC86JAX}|{8f){0+ur$m#k^Ylz01wMJISO1Y~ zJwwKrivYhnCKs#$?Vumr0r;jdAIflD9%dxFWF)T!M`euVx6e35#+kI8dB2RaIg7LZ zE#us|V2h0NT4kKSQ^p0?gXv+$1si2t$UZMTOU6a)?P9*;k}qY9dlbA7W{l&!FE0bH zfY-qrVaDZeA>Rcb0QPwKZ!*kjVTPH4TnK2h=70@={o3OV!)CAU1aLawZrpichWk_G zci?v!OsVn|7;=n>o{)OJ&@0l8jqVkl{oC)^^-r5onY#{jiJ~=+F%A zGUW`g8T<|WOGYYZntF?jnHPf=uwOH-8rj@;_AfFP zaE=R31`EI;8M%CCF5jQK40vVa@s0V0i~`Q70Glb~ev94*U&tutj*2;h;vPWTBKEWh zyJhOz8>8OsyF1Q{#d4Kr47_A5t%n`Ep$ zACgX>j7s|LEpNE0C&9ZuQDnp0d%s8->kY_#(LJO=38n4 z;0YPE<)9Xz$93F=hy8oFpZdk%AjlnjUYcf0}6xgG3bCwIG({qN*=-oj^n zgzx!Rv5Zf?_~V_dFE!)r=$ka-rKsIXxh&~Zr8o&!D`lpuK`G5nwo*D>0j1nM(yNrM zwnwRD*6L$#XC1Y^8-6=0t=j5Q+UAJ&m9{(P9Hkvd%uw0~Bfr+nBI{?(+!}Q^wU12bFP4+*8VU_P8R=det7K*;c}_C$}=AuDw!o&P%#bb3e5^ zH80AJ)4Y_ZBbv7$;fCS2xaL22#U{-^68((k|LPjAtgfV+m9^V_oU%Shd{|k(M6OYG z_wi3F`>CiKv>-RKa`?@z1%u;XQ%=l?xZ#Jpa<3YdqTGG%%au1VVWjdVCoWRntoQ@U zD~rxh-V5=gm0vn)Q27;cH!6R7TuAvJC7gNesjp3m`;NW$RS;Qw?9s1BuA4vn=vQG{ zY`h9HV&7L$s{5_sH^7QQ(XXpGH{nGUm&O*WI1rPm;teDAtN4}pPqZjLu~CaA$Cn&? zE6j;6AAT@wNmC3i+VtdhqQ&R1!PU7}?tCO)rau7qt` zc6R(DS~ff3IW1cgRikBV&PsFODs*io0E9=eq7tnPvT3WfPN*s_d4; z5h}}!ELPdU6Mr9mk8Fi|glqUwvQ@{$Bx==(Cr#6;vroEJtDZcmROK%75|!VRlzi;9 zvWe54)Y_|}M`-O0QS**HS@z%8%Km>3m2FQrsI?y_j#b6UiJ@b!l~u>xsfw3RzFg~K zqC8r+>f||EcYoYnTDLQCqSpO2>CamC{>dv;Ic3ByRjyC^R+Y8UVZ%?GRlaR|ho21_ ze%dSm<@xXXX4PLtovG??qvCbj@>5pow(9sPs-1nxy{c_LWru1vMyyfoQ&y4c&W+e1 z&)mqp@_dz)DbLrgdetA7^e5F%PC8Nbn`6pV|3K_|)gOtimUrgpV{fB*e~QnRFMRYe z`O;$#t08i9qx>0>=ga?wwNin&IF|xrNZSHe#BW!iByNiWk0p8)IAs4g{F++eXmt6p zC)JV?o>k+8iJONXS8J>u`;eN}CO$O$%v#f-1V=6VoP4!D5r0^%&%_t2_4$Zb)%s%6 zy=wg=GFNRU$DOOT(TT}wJ0qf0ZD+biscll?U23~3;SsgXi>D(e?)Bj(+JYA)xD>oO z_G$&+i+o2NQ8AV3SQTBMj^6msv>|OojJkTFCmnmmZTV@374k&BsZe+9s|wwpbn*Z5 zp4;~kx2Y#G>5zI7B0f>i$e5sdW<@=zp63!R^^QJ0RlU=$*ss1VF;(h&JElVYmqa|K z{?w$~H4uCHiyBxE6Epl4oU|X;Bs`OFOuzv%0dzE_6F}=zwhE5~c7vnB9RbQ|q)KU| zNi#{qW-?~xXTtjk=L1+P<7#jV_~U7iSB2XFq?MWU&pA)H9N}>Q>&;sLN`$uoq>uAS zv9h`VzmvspWc?!C40uZT7ceNi3uqC(1(3ewO$2bCyjg(n&3i#O6#&J~=ezPh5)K7y z0+b61z)C=>Qg|{*0~x}PfO-%TP6V(U&S0HpIv z%K@oO32AxBoq)bl_O*+AI zxCh}Fgf{?B3SR(74c7ee&lnlImi@22Aq)qAoR1`xT+98fWzTCr7FG|Yf@(m@vyRkh z-Th!E_$wgYt*ix4gSUlgW6$iTI`D^G1NKu*+Iib@z#6rDe{DP12=Maux8(rzDtHmN8N4TK5pW(Iy}}TM9RkwQ zkO!b|A_~ z->K=-t=}|#!6cWauW(8Cc!iYQ|Z1j%M6s=4r-s`&rG% za7r~}p;@IF_2wIz5j59n#-8L$HRCn&?%@|ZXB={tX~yByZAv-SeTq`9H#Z%7#k0u1 zRw;{}a0|1xP6vVqs*t2dX{~cQpa06lse7&K&iLd*C;jLf$c1J%9Xmxb&*n=$#+u!YX79v zf4Ije^?f^9sUO)F9(zYr?!PN7(tb&4(SLedX(uL+Q`$*Zp3)}RTa|XDvsP(SO**F8 zcPnj<-K(^PsXr)fxmByQHC7HhDvFNHW8PKT9;;1hubM%n{lhws71YeB&N|J!(O#pO4_g1D^pSSG(l2*4D}92iN$J9M$0$9`+N$)N z@mDC_<1A2mzf(2*;%WNk|Adt7bG z*p_^`GM+Q{E8|tiql~Yedd*5S-_@)e%nHp~WUtn&w;iu$eQ)+^cDyU7*`t$9&7SP| zjyQqHc|e(`C0oio$DXCk>5gBSDc1eUOmn}f%mrj|nYm7r zGFRA9%JkTuEAt*ZMVY(J7G=I`zNgHu?Cr|@-TFv#PIsTHIkx$}<`mcuYfhhQk>)(@ zYS*0S-REh}D`S4uoOhjO&7I@4XzmK9RdXwyHqCv=EY;jc>{!ix!F_?|zF}2p?twr3 zsJWlHuhqObd%EVu+ke))B)duTM%eM1cW$yh{3h)D^Xy%k@0cHGzR&zn^LLvEHUAZJ zmFB-`ex&&a?J&*%m-Uk7e@6D46=mO}tTFalWnF5PD{Hd-hO(}4I+QijeTlO2>?f6# z@9I?63i~N#t+%|&+T<|pesjz4yR%t)$8T5GYsqlk*OT4K`p|W%vi|8Fr>q~%Vr3mM zw<_zXxn9|EHmvs|^PkEdXZ@h;@lKbruXDey>=~2BDm&N7QFgJlU)hW8Mar(RvXy;@ z6H@jz`#xnqVlP(q-|P-$zhl3t?EUsWWxwxqYr&tbb}g7;^+Bb_e53^n&5g$%!VS5) zwBYVZXK2BL<|A70l6`^}ykq`LIkEN+${AtZq@2m-C(60e$yLrR)-L5Z=Ecg%b$XOj zIOfQ)M|9iV{BgJWjB*~db}Hwvd4+O*a{83>oB647N7@%D_X_)va<8=CQtnhcLb*5C zla+g;>qX_>nG*4n}1Q>9oDSK(>)+bSGmFI8c()u6&G_Y@W8I1j3Dy%|#BMpvH-H=Ez6@I~h#74C5rs&Jp# zp~6qiZ&mo6U8th4v6rgIa2{6CDAzeEN_O&8G}iQ}=o)jIisqYtRZ)d~SVgzF<5kq` zo~oig*MN!!+*hjTPSuPI>p?srN!1BEiJJh)zUR~vX(a3Nm}}`^Ng1MVy{<8 zjPsmI&P<-9l1r?;Dk*Udsie#ysatRUT_ppqaFy(}zEsIu&WkEJ;Jl=guaYOL?4A+2#`}yTa|LY>Km2D^7RM&bg@a{$>8E6^G1+wDL0ZH?7Pzf7i;~u`9H4yR}X$pK@N)%02EBt$Zi_C#`(XO4Z5_ z;hQVJN&k;lMY!(Lsst-cs}fyzlY_dV$U$BAXw^)6qgKs#Ue~IZ?1!{E#(7h#&vsp+ z)v2y3tpyk*w7R?2EPf1N&30K5T!f z)!*C8RGw`AN#$)J`Brm-%0IU@YRzT#ZmpSU-=;P5 z?GakD#H`nvO4lZ>*=I#)&1d#|TJw!{tJa=xg=?)japM1d%zLUk^VnnFY3@149`nvk zzTp47-o18{vtMhsx#w%`Uz~Tf_Hipx74de3Dn?sTsu<_GR}~8;&QQflvr-im*5=`- zzAHMdXjO!gr>J6^xmFcVI|o#;Ytnfn)X8JDF2!D`bv>^8hMxpqx7*Isx(}WARC$6s zhpamJ5>;Mlzo^Pv?eVId;m%X#YG>->NA^FKDR1W^^KW->;?1F>;bJm!(FKL z7ub8W-m>C{Uo~HUjeD`yFSY-v^-b<2s-EH;RP_w^QdQ?nI$za`%tlq0*tx2%$#_rI zci2~|dYhG?>gP-bzvN!7>Rs+KRlnj6SM?j#FRI?>+OFykU1zBJpp~fV&y%OB`WO3M zRsYA_qZ+wtR1{reD|E2Crz?wR<{?ENhZbAqUl8}Ib z+=NS542wYSy&xhH1Qj$v1to3+f>LeWYiVm$L|Kd?q1F|bZqv|g`|c4*u$!;UEL$FL*IdjWRL z=Z&zVjvs;@>-o1~M}RlMjvw*~uw#ffNB-J7ER2T^o%fT--+i}wKZTBD_W|f&`5!_@ zu5A!HirsfXhsXOFbj)x+EdOcvj$Yeo=osW%pyNdzt3R`yfsWsbx57@&b{2NdsI$uuzl6?R z!T@x3i#wq6P48c!^Ibj(I)5j0LzlsEA9Ur240L(DUqM$bzYn^W@ee@Pa_@gaSHSx< zbiMCxgzgFa1n3sUUC>=3c0#wGEr;$7+d1gIXW8hX|XS>X$*hP`(RkHg;k-REKN1N=(Zd&+$y?0t#90DE5*ys-D8 zy9atze46|d0ljg&6M9>HH1w_)W; zk3n#!xD0~3_-zpE77s#jx4Q{~0r5Bl@3Ad};C;dn1RwClK=2`V5Q5+EC!v25?}Gl> z{8!LF#}^Cz3;1m4Z{TyFe+8cl{Tum7(7%b#gZ?)DXV8B)pAY>H@rBU;C|>~mgTh_V zf0lPc|9PH={^xBkLjOxPHT3^hXoLQXQ*z;U(Y+mRU+lgfZvWI52m5)S9`>&&>4E)w zeDSb zS~&O;{~R2A&;4^a_)C8&9Q=g$!NJdj5;*v|`$urd;je&0X||W)P$^#ohw2^QMt=Ol zFP?=%ON2r=)M$GJ4z01h3Wqk>>~QGDl>dZ7Z}aVN=))AjH_r#~+=nC-}IQkdySr|wZpM!xM_f#0jwY?4ly#GEJn8TOBK%MXb3^ec_7&v4b zf`JEo$uRJUF9imk@Y!JCC;T)Rcwblm1Hb0WVc-kC0tUXcy#dEGJ{FFp`Rs74#OHux zGi@bsY@rwn$3FIPa9nMh3&%C$3vhfUKOK(WAiM>~pY?wP$Di}1!SNsYoN)Y2z7kFx za=!s5PP&KS#P`J?!-6GXo8~xA^FN+aMGKSp<8)D} zFH`z~5_|3}2vugKam~V=hLO$<( zgye!7q1EDWk%aK)n6?QYk+cmHt{A~W@~;h;Iq|1R()1Z-N$#&PE%H7MH$3ZJjcHNA z3`~oJ!qn#rz>=SfhJ_=nJ{}%ca zp9;N*k3qNLQ={n@c0(}Ly*%=JH{}A_|9ZZL7+D1xSziCt3jhPB{D*Uj`!9-AW*O9*!*J??O!% z<4}#opAc=0B1(AzRftA;A&{jXM2bU&@oqw0ajztLu>+6a+mC0NXl(^ou|k`Z4TIWfEJo*KQz51zq?U*wpUWQd z%x!Sg%xkEeZgn{PR?ZRfgp|%oayPXEnnxS_I0W{>zBok9e6D8hq6T|qpiyc>O5J5O zxxHwtEm8{66?F}vDi_wq)n`ccvFgk#nrDqRbM_F_1_CXEpl~AHV;!WVf~sPVA9v#C zLd#v8gKJoUyn`ChIqDiKu%sI;QT7=)qWzp6mgC*LkUK|3N{bpo_QsX|naB;aGbCN} z&jHWfESDQY_GY_1#5lR-wG9DBh-&1lk@~y_lo-`y4LCT5-S0maemX|#}p?c;oYIs5qVDG7GI89S@MPs>tFb&%pp0ERWBq~j)gh(oOQh^!@Pv$hOk@&4o zcmUd^R;5Ic>dm+diKZE)QP6yjmT7u^7#gKbNT-o*6lyQ5!>^`3;1#(TW;5Jtv!J zguQ`VVdeaTCR1R2C62%iHZkdqu7Io)N&WK<@Fb5=7~)kru{x$&BXq~-QPu-%1fUbpW;ZUF+PoN36ZM8T1tpR_tBw*~1OM{$j)g>DeF(EWTrn7k^ zew?$z@loUU2AZJR$D_i_+4Wx zO`-PX_JCc_P3Fjl)OiNE8$&8Av^O^q6T%SPLqatY>w(*RHXU+vh>LsmAE>X-w*<8AixDe6fV(Oh0Hj7dWcD%MZWM_@8X(P z;31Ov>`g1AzE!wfNjhXSYbEFKBMa@6WQl@9YqXqvGzU-{LrW2DDrbDa5U>{q8qUK~ zG>gjg<^_#tyzP2>m0ddOCe&migjuBK$AM(VC?{dW{?e5mTH_jAs&-zYNY^@-%&d_{ z#g)x#2-S|VsHF=F8(bmUQiP3U^VB@_0ZQqhi11X-Stwo)YL%7rwuk7thRE?q{b!M` z*3ko#yCFp~oy2)LM%NoHuUDRwkuIHdML9znCmwW2iEEIX)nq%DlmN@PXt|FCkoMLsOSM|I4n!-dDh{ep zhav?qLkPH;6!`#z7B@3QV|A>=ou+}(a7E-RiYpqVDK%PqVvO`LIyCfw=EfG;ouZVX z$U21tFpPB2QPSDoL`+j%gUYJ(ODdBdYI8-jSpK}pHP+rnFsUAuq=vKw#u`=9aBZ?~ zq(?q)a%ryFE1>yqlW8KS8H$qHh&4*r{LfP<%2A9SX zgzD1ck#4}H72_g{BdbK&+=ff3B~xo8id03osmXHWV{=AhgC2RGmsL9&8}+!F=dCgq zUQdL>aFc74TNVPYTkDkdJklKLEo*0+%a5fhayKGN6}clwijJUEcZJoD3@@K))a8xb z*kHubb7Lct+90LFNL6W7;f(2aJ&J3xB+qnQD%Jy&2Pt)Wgh53ZXy@cWAbQmP6Z8KB zhKV4BfZz{YNeFGl^T4x?xps@@N@|Qmj+}DL*f$|Y;GnGtMOTpch4`i@q5!#gzFS|6 z*c>UG7$+EsM4&jHnn+}?9yJN;T%&zQ<+f6SbfoVU)VhYPNF|bbk$932h2N@l2f3|8 zbkb}@$JeREkCcVk!&6VOho*+vgQczPfzmL0$CNO;f65Shdr6q> zFS4=0qA=T6G{o+k9AJYmiHO$thwz74pIqZCUn4RYsV&^)-Y^^QK`q(h*P1(=RNeQ#F zQ-;`@>UefWm5ZHTUd>jN53%K*A$FQ4ft^xP%}y?AWs8f_S%EKQ`7&$L5_e%cTS#G{ zApaDbKOu&lly{2F%S~l-CxqFY>~=OgNzJY+2`UJ6 zu9|b|@VuIkrgm|N>IpgLlTS=^LQGEx>K83;7^J9u{?6WBNGY!g70hoqt!QjaDfice zT1eUBk;?6)tk+|C5Hs<)4TDO>KK~|gfy*U*ke5`DXyd6!x^eS3(xw|-n>OLcSPvI9 z?mccKsY1!sNKw9Ej5^9c+Uu$p^*=X{g8^{BQ`BxKhfUNHsD&nY08YUHFjFN|1x$lR zXn}(egesT{{ctzT$9@OlA#_Y$9H$!gAhi+pLN6SJ4`2$^Aw>c6pby(>VF8YRKRgA` z!>iOrY6rE43Q_|&YAtL;j?>g^oU<5aVBL>1ABB722QUcd;04$L-8lYXxC`!shbW*X zQbp8s(10C^pbTc>>`QTFt6>AK?GTPJ6<1gTJy<({bCPu)f;-_scm&SE+ql|U(t3~K zcP*~43g>HvtvCl+_bFU?AxuUYRO9+@fn7*dAm=<-1Us>O0ERBUAN~ry(@XU=lrS@) zWMq-*=TJfjFcdCS7c#%bF&T&g9mE0aiHV`(RBBqI(keiufV{lI__6n-e4``YK{+TY zo}wI4iXmp@-;b)!efu}MlYVJ<>u|A3IlO(Cr#pwYFu(rWJoWU87cTZQ1^9VDVHqw~ zSQRNijaw2kNY8am%AZ6YdAUky}jKG26aiucWlpGbSfU>e7Lvh}ue9B}oajCq( z(~5N7U09G{Qqzh8iy6NeE;R#bqCl--ChJw|{G@ej6LYipR5pXl=F`|r2fehs#9?xM zkJ>_+db8H8%jzBZb~r0NHNOB`Q(eVe3Ryv)66hnif*91xn6ndfM%;c`;ZOnYdTdSw zPUgI<_S31#C5x2Bio^-jys@IvNOe0k)w4CukuApYW%6LQ8p_qph>YtX%VWxFal0#F zF|G8|71P)hYo#VvgPSfSuQGh&=8IA8l)11#BvUeKCc%_oG+QF?1QVCerK(fO{zZXT za1=vUl|g4voWhh~x)v9{jl4S}ok*>a3~aVggiR1BLG^TH>w>K&)6S%%C`!%fsvDUDn88LeRxX-!tvW_{GfkMEq6mSoXJsTCHhMq{-ov>BQE6=#Qw zKN!9XQGP5=4g2}|_(e8NK~5}rg_o0Z86H!JdutJ2b9XtP5@-?DDFwRmZB+8aK4 z>rLbg*MLJ=jg}_|aVL6gDwU35vULF2c6(a3j!KTs&b{S^Y;~G&+YM>aQ0BsSSv<-( z9xwR|WgU;Q;UdB+NT3tqi4-le^oa^GmsGA0y%9MP3lXEhlb#AL)|fRbF5#xTOd4HW znbTm{*`-(J*H%`&b>qr?xBT#qeY?C>i|4H0=F7-fpx8>S>9J=iP01?rl-QB?o*uS5 zZni0CbD~0PF>bWXndrQI`>TKI*;KY|{n=-4@VDmIQr;?lGtr}3D5ozfK0>?W^q3$o zH#ZLyEU!*swRG%`8?>|<%7$F1Lk3H6ULM&OuJ#gOII?b8Kd#gc{&E2@)b6frZo4(Z zo|52n>a&YWV&hlo^;>EeY%v&06ZFw0gE@7UF{y8BqEexL&lqpc&rUNKXM30Z>G26R zwZddpD$OQ^N~4ZXIZN5LXSkF}37Qna(1s^Q?GC?7w=rd4feg_9P^W`LJD}AWl8-`K zu!2q)MZa4iX|3@JZYuF--DU7A`FHa;dqwwKRC?lH$xH zOG2qeNsmIaQ2NR%ER2_}(|C9quMJEEEw5LB#cRXTcsVAG1d&F8K3-Egt5p{}H&(;Y z+E`z#?rt`DmsU43E>;XS?6TRl zMbYMl#CSteO`_`0N(qIzwxWw&7t&lB8Zpfz5p20WQmhOZ4|2ep4$1&kD0S0^Iw68|CYP}MGBjk^ZcEaMbYaTV^Co3ybpyhE=aSeVG<&Z?+-WkX}v=D|RV zF5XpQv>Y7noHcd9tTngRI2=A^YW#(-hm9dN8L^fWXEIKkSu-)?Q2UQQ4&1tey1pwl zi%FcIvJW5W-tdE`uV1t(doER5Giftw$vM=LC5SpfLS0UFb`GMh@LxvVRhawqD$FfM z%+2y5=H?kqdUM(|V^a6E5l1J;h*R4L-ga`Mc-w+_Q*?*lRc?;p&G5K{Hv`09^0VI& zaZ32VfVj=*3HM2!FvDZaa=S0{gDu1n7GCm%h_-*HAN=J1XFo`D;9%hYtshjr_wVt8 z^ovlgI{NSMgNl(8ePft3c}lAPu^*&Ielv>7YX96X{<$AiD3ztk5#|}pB;rALCMs4% zykH>)pQyi5xS23kP_*O}dc9OC`BawDlQm^!n&F?w-=Kt?uuJ_m^C==c4|9>Vc>YPb z*_r976U?z%bYW?_#Fce*x+Tk&=`iHaBWGPm?t=Kjf&#=^hLS~Yuvq*ctPI<#{QM!p#t8ToAF?LUls`?yx8iKgzSljtPsL9JSM@s7(h@||fqM-s!^DC53NDKY%}@WkXG9xy2My)6& z%}9!DT+%4=ikBQGE`*U?IdOAbDyL%9k+pX(GitQ;8Z~&4q7O z0YNMgUjiAKQB#DEcuwY55zm%+)4%H3V$|1-xwf^#E5}?L<*jUOxHZAlk(8uCuN<#; z*u4n}53OuD8S%=LIO>(DN{i%`YfPqr$|bvvV_wh2N~WfVQtXcAQ7;+$Gt*8EU#B9#r$HT~d@9dsdljPD>s`mb6@F z8aImX0;i;osw=Rq<}nOS8QJhp!cdjwvOxCwNFd9lq&tWN6%OVC^EKv#SsugeX{BWe z@r=@eNmf-}p0Uh$1?b|hMx5%}SaYVy3w2`g+DKDfjxrU&n99ujR?gpYSn*=#wez<@ zi=|V}-`*>@I)AIMU75dq(x+VGojmh8Im1+FV=%+K$2OW_#=7&_p_+2at{-1PCpVLPwe?Amz}JUPMGdkglL82#83PUPXEp zks?KT(NnJX=)3Qp`}@83{yF=Pu=clSX3czS?PMl9tYxd1p?$^DaY!x^)zRN1nvN7w zfxI3%L!%zftkmO}s}|mOmz__inHBcvk_T^W=q+|dMt_Eldo2a&A2oOi#*%s@5!Pv~ zy4Nu5`PwO2);FUqHKu&a`JIhqKq-Rf%+_>}%Ib9IlsVfQ(-__2r(RA$PpEnw2yyyR zGk5c`DeLbxySwJHIv}MUSDk*vszGSBV`-H_jih-wUzxssRAKCGmKj$k65Tn>$J4@e zv=tFqqyb~aoUZLJ?-hS?*@77zS`ezQWMU*9FJ7-de@RnQc-m>f-Fsof`X;LC<}gCQ z8$ZyVwz2jyWU>LKYAL6Fh@ZBg^&Vx2hHhw0kiF8wrc;<6?6aasq&)_pS{J8Rvtdp$ zzbyy@7el8W8=j#vjLmXLXB%lZ7M_0SkZPaIBX8h*D$;8@MlhsS(myHm!w=kkh zR!~UjZh}^8n;VJ`t8Hzs%XDCD%z9g5Jv_Qdp+kWCn%;AzApZCePTB0xI|ebi&9cuQ zQ6;76(#AwE`9%6eDC%qQRr#*GOPxxfeN$Xe6;C1HKGGnWciI0=B?(7g402LKpw1&$ z3(k(-6Kest#xe4y*&_94o4DFmhi+B9tIqDrNcX|vHSobvdQB^Z#vr6Ds<7R9E`-Nn z(<#=tnQsBBQ#ugW@RUNFjQyE3!7GrD&tmE1aOCLuDib$q`b#< zpnrk|X{)UhJ*f=l=d-I5h)B{&^dRI0DM0zu-C^#(B#1Dz;LG|KRNovSU5`=IpLCvH z7Ys{-ALl^6lCwQ~O5Zp-v3nusHU>F*8u708ETczzint`GxBH;xa`QKPG7$dNL7kmilRN#m>TiDM{nPCw$m|g6P|okqB{*fu2bGA z`gCTL3Zm%b(+*Eic^YD)Z{YWI<2iZ-&vK^?mEDHg50+KwRHUgFu!MV_R<6VimLjr^ z`3H?FuMR$VLrP#AxMTArwPn(+j=b#*BKem67epJOyyfUjNc7XVIFvYlXNU8n)2&o) zRGeQnbl_w1uY~QX(l+rArA$sj4?o!Pcx;?By7XFia^d~c1>FNb)y%UwF7P97hvnw1 z3-;-^53juqwLRf=<=|CC#o0$*UL20@P7&T$urx5-^J-V+rv{vjVJ_^P$JX3y)8^%{ zUc?dO1)8RDdijob7B(*WSV*12=9Vf^U0tI@tF3dRF!`*iw)<-G;v;{&J+8Rg&CqPX zq1y3@-d&l!kw(=h&MzxNYb=vMF6`~~{gUxVAG)$RCU*LE?89A>X6T2~BGh$g^1`Ff zGs=43Y(JJX=`E;U=u*i!EWh?zXN#1$Sv_%Jztrq}E|b1UaP7?)-N>1eh4hif$(MEX zmCEz7*oYLL3yb454C{NYocEh;Vo^nimd9jX6iUq{pl+Mq0cws9FRDGXPb)|n-iL&^ z)M}6}=SgK7NjP{VycO+V;AHSob?whmz&Q|(4ERS1ox>5^exs?2 zwjy<-X(e~567$PUB1u75SK#2*HrC~BhtuAq@~48%m_Ul>BN_BmjzZLhj?{%hRD}d+ zdF^o-w&hpaVEPn&Dy?0GQxs9on}-OKW+CUI^GmyOi;G?eM61&M5-4)gYU}ZovY`gA zBKH%6Af^xrXomgTmzpI#+vSt*yzVH5o?zkbL_J)zx%yNOK<~7HJA&XDpG^RB#a9n2X z$s$E#*X-tJ?9BUlhHb90D$=H=xKnR-W^ZTg2Fz7XY~phIZ@|yBhd|Y!aOWWC%lowj z=>i({O?>&M>76m>z#$DSj;1a#es$r3k6znND?ST$Dy3^*&{&ZZL0`eHl+88y#r5}XNQO%fsPdxF9MdNe>x@z5b zH*_gP&_t7B+>1%2PN?5J4Ccxm9`QPC6iaWcp)H{bc3~hrB_lEg$@^Vo1d_4P!)&LMa9Efqu5`keYfBgoBXHq|}y@lzlVFF)U z+eg3c`B>)r>jon7GP$<+0RtoX3BS*p2aVMHK_tWWN}tCAk1QftIM<6x#y{fa@0i)} z=88+8VLdmP`s{RWu1ea18!=MmFBf-?H#$_KZRhvoQ|Udo-R1U`%sy&&o?*LU#hOKU z>K(ne40Nm+hzSXMX?Fa6){EUMSM(f63Du7sGFYCzSX!05mVApgzizUsjybn2B}a=? zutfJnaO`-(qLjv$G}Ey=eFc;r1(yC($r+DMgdW>U9YDFe+zlS+cd_^0GxMIlti@>; zB--n}{PCOz6}rDwgwi+Qu|S4!?W8wXKv7C+?`*6R-5J{1kg(J7g`esGQFHk8+GH#d`mwXmba$f~}jK4H#G z6I*fFk@aogz5}$LhE4*pfl9JAMypzu`SIS2uqqSg#rxzz*tTLXe|A#i zDXR1bYE_Z6H#9Oo-f3-mqoR?qDyuMNgWNRZq%~c7%a?lj{pY7!Bh2z#K7tvuo>|mO zzsz!84oN&|V2V6e1ErOS_xw-7Ew@8pQ`G4JkkJ)P_k6S=_Z_Rr#E6RTt0EHK*qC7EE4) zDG{|cw^4U?OXk#PkD~@$uVm_xfk7c6N+{pThDU@L3V^=nm zow1%4LpPZCUb(6cfwt*|+q6|*XdQChp13ZjcP6R0Fwm$L`ck2=7(`=Xq&2@5wr?Qb z?Bt*7EwjO`^N9yG5^^dY+UxrIoMY9SjQnQh@^*#7F*mo8{i7aCW-HEFj5SMQ9PE$H zvL{z>-0=B0yxLBnul}UJO6x4aK9Xnu;kZyktf;X;m&$ltc#Ql;MuL}eUTab4usd}p zHO_dn%F&O*ZgAtaZDyy(+tCs`@!dMHz9~&lD=lZ|_IWRmr3G|g(SPR!XW@jc#LW;hZ$6!7299y8gqMDnj{62>LuA< zbl+Pw+!CX4h-Gk3ykNx)!kWAa_0?n9Qhw6KvhZb1Ep{}ShsEW#GR~^V5**II}<_rOffH^1I$%t*w;VS3>PCA8PMHPCKR;Yw?87Me?s;cI%>c ztb1^v44-YDcL%n!>Mh2Jb98pRoHv*f9Y@K_Z#m02g}-X475 z_8~|t+BRuS4g`|ndf)|nsZ-_DSS-Hdi<}$Jyu@z3?a@+1RLTr9f*Z*#LTA=PJ6|Bq zw%X<7Ma@G$cr8Qux#Z$v^)wks7ao4rDSM{BmwC^RMW@_DU7B<0t?8&mr$qliANjxP z_=01%>|3f`HV;Mb^cI}Y49b)kmmvv$aE_+IsePHs8R0I7dMq?5)jEFc)=&d_vUA+| zzCu&ft0TPcMMtmFRPN3+z2T%Lp(xK~`S3zTWJ7|CXgd0Ns@Z5>9P-xIJW&w6?~H!O$p#cbS`gtvFMsY!Qfh(=LNU_GwCcjd z1fb}l@hmAOrt;ajjO((n0D4`jmFv0Jl$G@|-l&Mhv)r)_>b2iELb;@oV{v!Z-Se8A zh1>g)ebb2huVV1?A^AnN3AvzwHP@2H1U93oLH~#3kGq+iVQa?bGl{c{%eEfR_a;3W zJPa+8P{Rg-BSItP^|*sa+$N=G3{*`~l=r1mZE>Mi6fNzy^Jnm@9Fn%F8$of@p0zpC zPFnOrlzQ)$(Zf}Dd-5C~B#k{WmPz!xq{wf0FXzMP@M>nu3qrRg->$`cdZ$uOWsp(F z{fdCTjt?e9Zte)ACcCqJ%K9R0(~2h2()pz3L%R+0^HC%0jW~^N^YWALG3?VFui_Ns z%_k%tm?XV+U6KUDB3o>3)c75#?`gl@j?g1sEMir;34gZ7O@5x@bMaj~lZT!f&{eNE zIg&YMMMKhZvGu8Rw&y}{`-gXV)iX^m5cMY)Z#5%;Md!w#?a&I>u9;`u<3?hNAENgt zwhJ$6R0A6`cEc^Vf?2i&BH8;bcSJrT3fwuuw;Wc7NhYkXndl?ed!6ET;;_NOh_}^k&nd*$Ews4^-j#1{-2r< z2j2Gpsn`5aM+Zzi7LJLId$>jHP;Luf4B&18TwK{AUXW$7Q_0C@a4empKjW6i(^OKzoDsJHceJrGhs|tLTTyp;bFt3j}#RF)(E!BeT*pEUf~^Gxo(T2(w z;oHZq*UK$(-^z94p~dm-%g;&Q%GE+79{|jK=EX&ye+=XLbZkKQphD8yu|Wn=vjuW8 z31U3e^hvg%@jgVVMDUE=w+MX4)F$=sm(bRm9Vh=9W{oxQ zmlL>uH>!UXe<|}JKjAW_OB8Hz^l$vubTr!nj-Ly|(%yT{pr1me?OGded&#tdp6>Nq zHi7o0_?X7t=sY5mS`1hpF2z@Tbf!#2pg3H;Bny``CY;v?-tpC(sOWx*MNMp%lAnMb zj$%;53f`rsi0Jl}x`<*_Ti|(CKJ-ZC7O7{TUQa0E#dH%KM`m$Mv?ivLHUeHu2JLZ3){8Tils6{0y=Pz+_%m zHOx8zi4-{GgKA|PZ1nZ4)Eg|(OCE@<-)<-iF@EPVxOma&{3a#V|48Eb;G>gL9~}IQ zXVphDEkKbxDiFZV7FtVsa_F#nzZy3F=Ei8G&q~YZ&fpf=no-vNCHf8prmUriNj*US zN}}mPLe%G)6>w27%GiM^Q?c?$&H4G=d*{ht`QAUhkYtQL;^^b6plxMvqi){qPO;}O zTVsoCskVenN8>J&YKrGr-8^X)0T?gG7V*QH-z_9?I_*RRuSn5s6$;!_L?AmJZf)p`%{+$j#ic0;{sV&RiCi$AiokE@g^(U@|x`59rT z3&K3<8?SK_8;=X#ZlaI2Vc9;+w#~C|c=fi8D^J^W%jEl{1L}YachtY_UQZz6F(~J6 z&0jaNhXFu<-#4;1@N&ffwJ=1K4T^{YB1zW7uYj?Z=5Jfr1E3%Y(D(b-%gB4WqR@^Q zBETABhjo$VdS6@51;ED* z0eCt)xe(xHAkf3ZL(~H*io@Fh!BSFEKoA57fryYLL4FCcHOUZnd|A&kW@M~Y+_5E8s-yuKs#s>XIkgg=W)3*?9&_Ik6#u?*6 zB#<2fe{;wN4M&p)mWad4ed7sg@$Bmbelc?AArMh6Xv}|N?K|C{1P}N>IB5S5`T+dh$zNjmZ@T`b>n}0zmxTYGU4PT{ zml*g3DqND&(0mGnQ6Q%F-B)R`tg4}@$)`^J0167>JsihJI zjkCf0Ui5%L;O}c5&ouPaLqP`zY=L(G6cnMR^w}=K0(^X+CMTL~%OHV7kE`K^Y?qY- z1dfMhEn8&qWx1cEI&-XvHhU1jEPdVjhHk_O+WUbN_bgV0BU+A53uscN7L*>=Y%e*A zEYtym4jp1jKF<16YCZ87TLxMX03tzt{p|ol0ODd|P%*&QE5BnBfNw2;%O4n69Qp$W z0ZaXWiGj)W;Me0jT}cReNdFlFgFs~d|AaxrAwOVH@Q=Dsamhc+K_HUknefl{B*bAq z=#smI{v=-5PcX5cVB$Z)Bz}TP{sfcy5rcq!f`Na;$ZY;;j3lA3ANZ5}krx=~NA6)z zDTzPx2ZNDIp?~m4#G|lI7(4^5jLdJhlEnY|{qyS`g2EGjoun`r6e7kz%gd{*qryP@ p`@{t?(Efk;2Gqr4+yUQQ0)BmeK@y$GXJpF$?6epN0{PA9{{n~{S}Xtn literal 0 HcmV?d00001 diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index 7133b62ba..24ba23086 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -216,7 +216,13 @@ protected function decodeXref(string $pdfData, int $startxref, array $xref = [], $xref['trailer']['id'][1] = $matches[2]; } } - if (preg_match('/\/Prev[\s]+([0-9]+)/i', $trailer_data, $matches) > 0) { + if (preg_match('/\/?XRefStm[\s]+([0-9]+)/i', $trailer_data, $matches) > 0) { + $xrefStmOffset = (int) $matches[1]; + if (0 != $xrefStmOffset) { + $xref = $this->decodeXrefStream($pdfData, $xrefStmOffset, $xref, $visitedOffsets); + } + } + if (preg_match('/\/?Prev[\s]+([0-9]+)/i', $trailer_data, $matches) > 0) { $offset = (int) $matches[1]; if (0 != $offset) { // get previous xref @@ -262,6 +268,25 @@ protected function decodeXrefStream(string $pdfData, int $startxref, array $xref } if (0 === preg_match('/^[0-9]+_[0-9]+$/', $xrefObjRef)) { + if ( + preg_match('/trailer[\s]*<<(.*)>>/isU', $pdfData, $matches, \PREG_OFFSET_CAPTURE, $startxref) > 0 + && $matches[0][1] <= $startxref + ) { + $trailerData = $matches[1][0]; + if (preg_match('/\/?XRefStm[\s]+([0-9]+)/i', $trailerData, $stmMatches) > 0) { + $stmOffset = (int) $stmMatches[1]; + if (0 != $stmOffset) { + $xref = $this->decodeXrefStream($pdfData, $stmOffset, $xref, $visitedOffsets); + } + } + if (preg_match('/\/?Prev[\s]+([0-9]+)/i', $trailerData, $prevMatches) > 0) { + $prevOffset = (int) $prevMatches[1]; + if (0 != $prevOffset) { + $xref = $this->getXrefData($pdfData, $prevOffset, $xref, $visitedOffsets); + } + } + } + // Could not resolve a valid xref stream object reference at this offset. // Keep already collected xref data instead of aborting parsing. return $xref; @@ -972,6 +997,19 @@ protected function getXrefData(string $pdfData, int $offset = 0, array $xref = [ if ($startxrefOffset > 0 && strpos($pdfData, 'xref', $startxrefOffset - 1) == $startxrefOffset - 1) { --$startxrefOffset; } + // Some malformed files point startxref a few bytes after the xref keyword. + $nearXrefWindowStart = max(0, $startxrefOffset - 64); + $nearXrefWindowLength = $startxrefOffset - $nearXrefWindowStart + 8; + if ($nearXrefWindowLength > 0) { + $nearXrefChunk = substr($pdfData, $nearXrefWindowStart, $nearXrefWindowLength); + $nearXrefPos = strrpos($nearXrefChunk, 'xref'); + if (false !== $nearXrefPos) { + $nearXrefOffset = $nearXrefWindowStart + $nearXrefPos; + if ($nearXrefOffset <= $startxrefOffset && preg_match('/xref[\x09\x0a\x0c\x0d\x20]/', substr($pdfData, $nearXrefOffset, 5)) > 0) { + $startxrefOffset = $nearXrefOffset; + } + } + } // check xref position if (strpos($pdfData, 'xref', $startxrefOffset) == $startxrefOffset) { diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 62d81b49d..aecda5d5b 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -174,4 +174,11 @@ public function testParseFileWhenObjectHeaderIsNearXrefOffset(): void self::assertCount(1, $document->getPages()); } + + public function testParseFileWithArrayXrefObjectReferenceInStream(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest804-pdf.js.pdf'); + + self::assertCount(1, $document->getPages()); + } } From 56d28b9302c8e7d6782328e83e9744fad434d4e8 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 13:24:57 -0300 Subject: [PATCH 33/47] fix: parse xref tables with interleaved comment lines Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> (cherry picked from commit 3e2a9c66d796c2fa707894a95f4dbea2677244ac) --- samples/bugs/PullRequest805-pdf.js.pdf | Bin 0 -> 401129 bytes src/Smalot/PdfParser/RawData/RawDataParser.php | 14 +++++++++++++- .../Integration/DocumentIssueFocusTest.php | 7 +++++++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 samples/bugs/PullRequest805-pdf.js.pdf diff --git a/samples/bugs/PullRequest805-pdf.js.pdf b/samples/bugs/PullRequest805-pdf.js.pdf new file mode 100644 index 0000000000000000000000000000000000000000..132d043ff50251d61021162d741bb6cb36f5c8d5 GIT binary patch literal 401129 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 z

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

QSm6x~* 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%0AGGsO`+?B3Lig6bwSpcydW5lI=U zsD!DhnIqT*|LDJbYatVoOlWn4e?6v8h^@`zWn@FhoX=m?jQ}(^sR6g5!=}SPf|YEn z=B~C+Y~Y$g0#IFgD#=tSWLIdYAi$0q0yio^EqR+p_MX>i6f22To9I&Vo!;iinB9;R z!-KN!{7}^W!Nd-+V2i?aj)+Le>}o!G@)2C9^WH8kvz$kNiSit7~ma%s@(&$X7usF1kJ;MaiUW{swEGq(ZkYy3w)sdjY$azPh8C2OEj2qqc4ogwm zHsk?X9Nk1k4#glT14*_b1CPOSZHh1BYN!=E^Hq!-Nab81Ws+Hoh)G0EX1QPP4>i}< z*UyVZNe5MNP~p6>!V#iMUU@|n9RfHopEiTUQ&W|yUR5AJdL;_zRYNK~h{Ku6v|ZAlIyhJjR`}BIn-*$$Ku__C zA`zD#45Ws&zKTv*MA?}fTMek}3TEEeVLj8$*IM!F7_Tl@PZ4(}iCmq{IDw-nzIY;9 ztF5llYmjO?9=rkIHr8t&rv)&_^DJvpTj4XrYTjajxW1p*8b2|^>cb()uih6eG$*cF zfp2d`L_C+Js!5xw;I$%Qzl`+NOBBLd8YV`d+_6Fgk|-usXI-1G_2RXec6EgEofe}* zO-04Rdb(H#W!Lnk3m2$|K+q2gH?rr&Y8$!>3(;VoHsTI2?pHXT<$29Q=OQ^TTItZZ z81SPK$#+^o5mbArKOP%4TZOWmv4Nhw#RZvLjz1r&BCEgbE2;uMRVY;OR2u*}(5;>m zT94^-v|&FA3$$0lqJX{1MB^(=B8-ybK#Hud+epi#t`}$aZz)M>kRc|5o<(14(7d94 zvkf-|?1XNKDv`fZ;SX#YtD>MpPcsM)PyLv7u4* zC`5`sOU^RUaa~C>Vuhq-zH*f!>i z6U2p=&yc2t35CZ*L9S8z&MGcV5uiZcq^g3pSu_`?`a>QOm9poA)&2|w)GO;^f#ryG z1=Jv?POn_h`!(Z&Q**i&Mu}Cfa?-08iS|pFh8wCFwJ|IHhe@!jb-(DHyDV5knm}dBkk=P?BIo^HpQ!_T~V+KFXHc zTVpq6Dj6ako4cKrh`HI+%rGs;SP{nzgUXOVnTlNSp;U7)6=)94saVDs$zFU?@fJbQ zo~f?>z}pc#0bEO3-VYr_RoFp$1!__S161HKBDM^u3 zYmUAqh}>r?A~V?##WZ*E_8^;d2JEcFk(pAG*Bk)&L0#`o8rLAp+A6@%O#^k~Vt=7= z0dmZg-Hx0WH*0bn%ropp(#cP|%RizQ!GsuP7T-4*Yu_lSXw7BV4DXDXR39=1rG!J^ z()9*2{YHeO#y$ZK^7~~;#tNe)O~TViN3+&eo42u;n2Q#v?^Fw>1Ynj49ccmk)cM_| zus5B^p{AI=a4`thh>i+EQ9D&84c03^65224RE7!Sx;!xvgDMPG84egyEaPLus)<)m z44B>L31c&Xi07M#t%VW~VNoBwR-#7Gnd_xr1~HrH$x{xztg114k}OMRX!ACk*#S== za+iRfi0pGP)tV(dQESeYC9$cTfniT#{rwP^~#}-rv0E=f0pvVvilk? z;PpDJMr-*XD@jYgxPt2KiH7H25J4OXBM}x32u%hrfxw2vUBwdDRuWW|Enk-Rbm6oM zS0iStw*mGAv7&!984t?4&O+=#TAvXTdJ|3o365GuLX258Z$V!eEYwTjgcM_=0%U|L z0N;MqX)V1vspY6~mP-bJOT-?&1$1@TP_KRj60?STfnxV)i#c)b-lP~hdyrJx&D?+V zi*}$CS7Gi71m%}w(gW9+)VW+NDvcPGzT&nw;g)h#tr*z1{4y0yO0zz_o3s(_v{TWI z`XWK1C6Yprk(H;=X!Qkp)~~b3 zmJ6T-Nv@1yDfsUVF=&N7TLUdY^b=}<2|8UfC>AbpfSEcE&UE$i$`B)e;&GN-JJg_2 z_lPvrf$0t9l<0;Wj4zjSoB{=H**yc22$o2s6^<(~ZnPI{iMY1?IIZ;z%fTfk zceA7C9c{S@PDVuYtL9&b$`TGw1`v)t!waav+gRNEcYhCvqgsf@Ur>h z($a`vCbAo8ZDV=|MC{K}rfGlcU_G8_G0`oo%h_ zh&gkQNU+*Y)Z+ujDKDh{98P?DwS{cDy%)sPPEJKXjsp(yfv26%Pn4k8dx(&OkG*?N z>|6G!qX6b=>Tx?Ns!h+41Ax&wI$s+SGT<5L-C!mDN5wf1nd8)Q!=zM#7B38fcx5ZI zBuL8ASGBR=BR&EgzCF?2Y=#Q-Y$hqa=9=-mT8L&8h!QC@uJHsnsU%-Ro084WOPEZ! zkqk2i)X?g^tt;4&6#S$H5ZWVB$YeMJ^&pJYAZo&V;J_Tvp`3*~@q~wjo;nTA(CM&Z zGXXni-O7rS`W`DI9z5)43?Tmr@8;m7B9Fnn6Ek1zeMdlNE!Q}RnCG>5B|%8AoSPw{ zl{}TI)gWeRYAGNLoB0QHlS}|=4(2K1QXxjkc(oG(3g|U%>z%1HVKUKI#6b=iay+2j zj29G7C?yRsi&_Q*pSJ3MI)z^wOH|M8j-H{z?8tMSLKSrqFXq zbW;+GHGzv1$+41@qhi*}!Uig+s@T!V7#}Myb7~r>JWn%*&3Z8e2APStE)+s1zEoYp zn@EVB{I0GWVeo3gh?xv%x}YwlR=B})$dkM{KWHh&9;0ui!@jQX$4ksx$A>JzuxCIq z#B@Clp1iS5br<}e!>88H>Lj)*q9~Jo+AA$#MG|$n6cBlBQeZiCjN*DgavtWJFEOlu zEyIp5^9wf)f+qK#v@;_ecmNt(UkvJ-= znGxH{2g2CY>e|BoMFiEMxT*%5EqprEXc&+k7($wWMxUV>_6jwU$YO#G`jt(^Mxpcd z@utwHQ5i{K&KB0dkyVjESJ*$~@m`LSP*leCQRe(mJoXa;_!eJf)_hlzHRRw^$Yc{_(rI@4j0ZwaWl~bwRvYc;$QWpZR+2K$(W3S1P&`4*Yu&3F zJ&77cb1+@&A0NSZ1M0UjoT${5}nfiznHw2)R;niqAH&4(J& zAwzwGJ=PAa&&V+4KO`@m31xhTi?s zh%h(j%Lf^RVYI$qBdbVkzQpYN@z=i>GcsZMd zpxacWgy9QJ8W`{!w#uERb5IoI`4gG@-So;j@GXw?N)YVx)q($`BtU@rjzO%d=G)VDwH0 zN7;i6<&c1YIH4s8KutB`1(Wvpc(2IGEH)r2^1xWt1Q6^sn8-@RnFcO#(tSzRjfplC z*WA=Mnr6(ODJEwXUD(bVFnWRyP7NzTE!<(e5fw_tPV?uyhqx0*HVjz?bCqy2c)3z^ z0N{{yS3=`*69=HD;5?pw4-je;PC{55H4AgVk9jtCSI6|;$MR0i6iR)nQ>p9v3q|QW z2ejSf6etRSxCwsewYB`D6Vw1I-kA+i?Pn{HbOee#_jEdopkTH)ko`tRg;g4Q3rU0g z+$#fRCShn1!9XzJH5BOOyZ03iP-Y3d61C+<1qIy)c^giwfsrp9(J}F$GeaV32QSR; z8BjyPdi{jK`xQ8$i3NPEXn@t0U^`n+F_DkB3q}y$n-FxBtOzdl<)i(R1*~Nedq+B= z5F%i4{3HdVS=pWnl&f>BzO75mX9W)ARvXeAIuLCJt>}BH(B#%Sh|4l6rz*8&`*&#M zQ&Sl@6F5~WrH+bt}DV^fLPg|XWAaM2pe7=@HiL+=KLk`SplwA z)`4GL_mZeLGh7p~6>Hf5gC=IG%O7AqlZ9H53T6vR6b_Mw6CJcO)k>_L7aA#5zCI&v zF%}edXmJM_PY#u8h#_bqAY)NXdH@y`mhj*pO+o0RRiM~dOL}IYb9Hi)Z$zJC|D3R@ zPS~S87260PDAj-Gp;Z|$)IvZPzN^|jqu4ejYHDc%NF#bjgSjc(jI$a@qiowyhDt#u z$*<()2z;ehAtp1>3t#vb4W2V)$c8|kJYx62)(F&xvXmDKEOf#4)NxTrpqk+%=P-?^ z(F-#Hbh1&`#+!;mDFw|uuoSu+oi-eR0HhR;Gk>zd9XJfqtX7Q2>`WvS5ORYO3pARz zlBhqxnr40SjC0{b2GpK{6=dZ_Ski`)i(kDQsBn}Ja%?;#bEkfMg zs7%pPPk@dY@hf5zc_k$lK_NHnp~@+MG^B+INl;-mP1suz_YyL(h@oTacy>%cjg!L0cdVH0rWMO6?HC}i;* zkBrHiM37eC0k!bz0VP0$ecq^ncW{niNa961=7`|hMh4NzI9M^I`V5D3IGn&@XaSG= z3kDiW$ZS_dml*}1Zd@n}9$r7KqCG<4RBrx4`HeCcni8+U9OtdoKvQm$8gS$tZm$t(AFy@L?cRR zo3QYmwWGOL!4posQ$E*#NDrikLI{8|YvDfnIX}&-OAiY06~Lw(mSRN&2>Ug*t-ny* zEK%SJD~m`DNCxQNDj zg%A-zUL{a{n@$iGMG6Mpa)lUm4 zcB2`hm=*@2V@`kTK6k}FZoDM5#lC_%WIfVf;$ zqs=-%Qm&z3Vqw`ia+gF_5V1X#v!K8I+vh7BN)Jm#KTjgNf>Pc1Gg8g6XPOm3mNQ1sc#mxsiJ4mab)s65|2v=pALQdo0T1S%ykfU*%oe2<*Y?SI) zd=-uiJQlWxT!gkf zSXG&_2b~I01Jo+j6_I96trQa%Ar?ORm~c&Xgi}q1OX($;gu@m|6bmkl^&IAg4XcSk z3SwIbCpGdY)lhZd7A4YD7|Fn!T<1q~vhuZeX%Z6H>YDSTn-Ex%#R~5lV1eph<|S@a zeo_GdyAlC}?OLHEk^agiO^XMq4}uTwXdgwvE}m=|&5hWpNO`ASwxo7ltN22d<7LeR z!l~I(9GF>Z%2GQL)i-Mg9wu4nK z_-ItV!WU>lj`K~_ur`s`t9^v3VxE9)mak+}KMu{elvh<@Cjvm<*nsL$>Qy1Q!A0c` zt<;(!mIc_8t#}?C-11}rk8597pL=$it?fJ9dHfZeEyP<+lWWz*F zs5}E=C%X_wsabf>PZSd$8zn~T)FsLC&YGEU)a;Ca*iEFuws~3&Y$vaMY68=22i$#1 z-Rl+{Ox?qGuaim$1VuHZ9HAkk@)B1eKunU5s#~Jo&;hz?36;7`73VkrGLy^nef$UN zJE;JgJt4*drq$vEry)@jD|(f3X+; z)J$8F^LAQ5VZ?e=pwevo>`3CBZ=z3{yAql+ZeFA?dJh8`%v_EoRS*s_7b`jz@XSOa zr}{eok~{&G)?N(oq)y_ju*TG|m^MKSWI>2!zUE==n6u+Z5K-pPCemawW`e%>24(ab z1$xpaqd1BI?kdBxq#?RTX{t+t_<`m%Rip4!X9NtAvvEFDD=vtO3ZJybD!ea^5duCA zVxqlN4zt>sDNbD3w1YP0T4CJQON{d7%Ic=5XvJ(4Bu)NQFG?K*wYLF+TLERs?7-8V z70|>4^n@QC`hQojuXswRNQ_8Q8cxzOY6^NeL1H4V%SlD!F5Oxh3waH(;G-B;1V}hq zbV5s+u{0>C2#Hw&0~mBK$C;$-FKhC+7n$WOL7d5L5GMz`l2j*KqA{zIqN<}d&msC16_(q zeDCqT4*TRgtKEzM@E`(6p)~c*{2?xg#ya(?xFGxOXC$;&#xl%R_9i7F%k^~uPWCzC zfeS*=jhVvQ7h1%$^%UGGK8-1WjQIC=#sVTK7y3w9>)yqG%r1Z(r)Hg{NmDc9*pM4& zTDIR_N_~@3Q4yMqi91wD%hm8!fIyMil zirc4gV6zuyLqL>wHU>=Q_?$=pg^l^4#Y!WMQdqq@atG9?3lQRkoq=Dr6~RQw!3VXa z6K<;Q5!L>X>z8gk)0tEWeTj=ij?`l@v4WXAXHkh21X-w2!VDE1$})Ra)RQC0oo}15 zQzV#Aa%aSeG;p27`waW}gqzC8J77~QMiH0Qvt@AVXgMM3A+}cV--d;ni1pa=Miq-B zwjM04;SU0&DjY+xXF^pLM8JNob-$QkNu=Ma$;LQH!WryV?RgTI)VpL5`=txEijs;m zl;bXHE96Q$2~}AOgz%~#)i6^`BC=3?YsD^%a7$roX+_h&Wh!nB%^W&~mk5>N*f|u1 z=~m##ij&DiJs%UZ%CF(L0ww*^MH z<_DTxApksj^A(>|7EF1Di|hf1y|r$NBD&4;9V>(@2TAgxQPOZUGTkJAhsw2zUHw9A zEEgH;m=`N$KjRFBMZx$GYQV4G;>$r-S*Zg^L9nN7yNh+F3^ceHmb%K zM7o2=fy@Rb0Wz!4Y$os(A_>pWsmM-e`FN(;4;&~qX>qF%D-QAM*HHv1-4+^{@m=a3 z@Z}klL>vs^%c=+&b{ObnKHdf?cxW`YH`CG^)zM5K8eCPM9Yli82Sw5oOoa{Db0?5( zSwBKlT^H(;XI`nS%OV62Z+O+g**#7H2KQ2UkF0`AD+kx?rm0AJovW?&5JAPMcBq3q zJIgYwoM)9vMI#tO!FVx|2r|wgSS1@)1)69yNx_S?)+N<8E7U@B#+Tv%kgSgvlnXtQ zXnQK03YN>a!y!-uLQz4hem%>8X!)#a2ymhVoeG@BZLMH$$@eCr1w&nm3-DxtA&5<} zRFj!(P*y$mrJo)LRQ5!v)TqY4d1l-~SDeM5Lj8(Wy)_0&06ov`vhRX|mSt^7-}FZ7 zkN(m=m98FqPz@_(aspF6j@Fg1ZGwNwD0+5kafKy^@~27>Ei;SmoL}AcvI@FAHcnFr zxebJ7&$blXd00^q4wcgH(vS_0kyDZM5b}hj#j~tqWE_&A=e>R?fYqO1ab(MCf!R1#g_^v zkK^7|aW7x&XL+i?7(-7`(mWYmpYLuCiI}K0LIOarCBg#Q5T^}FUJl8gd5K(KEgZC2 z+%Z%RuJ@nHH#Noqt3eQ5xn8kCNHcgvUkEhmDf-&}s)Rj!#pt_1?VYHor zlEYLtl@p(I#6kVk)PhMOt5WS;G@`ZyPjhKBIU_18v0W4Gxf~1K z%O{GWk-!IdxE@LR5rCtDOkY4vJMTmPYo-;srpPjiN&&R;q+YR>rziu3qwQ=(=f&gY zHU4ZWQq!Thn_oACb}tEX6Rj1~-o5vtO1MR7)(eocQ~+h-Vf~kMENKoqHU%*5|A{a3P0wc93oHVlZLKIt3%=-P_6%MgqFz=!el`R z@&dVRYxPT2nFmRdFa*sY=?&{5gi#voDhjs4THPjfK820E1i^NBhQdE}&TMB6YWOIi zN(AlJPKbh!xhGO)!6un%B)YF%q~(IzfKq_7g1(CVoYRW1UPGGAlV6t<2Hg^{<=nE? zxg62U2sW81gloQ6R>xV!?eohztDtitNVbSiK}H&QQY5U5rasJ!vg{tO}hj8Sk1 z2syH?+9k_NDm)53A|qeRjQYZ;?#MT>3W-0+JEDVYOFhByG~h`!UZzK~ClcVZ0t;H% z8VPR7vI-LzD>!M>`YdD`1!8c4a2%g&67bHGsS^=A_h*vE(FHDnSTeTDakY}YZGy&CXctmBAp6QG} zvdGFvR|kelnvH_-UOmvR`GU6R??{r>^ooJze`VV~+Z!2nr6?Uhs2B!r5@ zv9%4wW!Y0gB}Oj>gm9@CZPnS*Z`g1?t4b~Cqh=2`w;OM?!}0&_-iaG%MRLHaH!03aUrD zA2l*{epHoi2p`ZI8Bt0H0@jRey}f|QpgOcg#u->bq?0*^9Sb#P(ZE{F7H7;VV0#FR zIqwQwGSwgE@Qj>ZkaNgP#HgeW8nG}BPKIvOn0jf{qSPQ>a2gLVy`byVYzJW2iKOn0 zX>o$$dM8-}sLYlfp~j9v4pdJCsnp~O4@-f6X}w&`V$mljwo15x-{5 zkr^SZn&hkSJ8yeufoj$iq`Sh0BV~N;c_Ka#vc=W3ZP~RDLPB1^mI29*l9=fLUXP7M z!*q&Ov-|2gL?b{2=}_QcBEY}!eMa{yOljauQblC^}>Vfh=sSqEKaRP7tn z>ULto-tkme0noDq56?%ySYv=I{Tdgw% zO6X^`6qaz60o5%)wV!YjC~ZcjeL~m#fHmbcD=p7t$ExUrd|8Z<4czg!WpG@urw?xF zq|sS#h|#%PNyGewr+Qd@Q5~khre9S#GVOHD zZ_+_7V~E}fB`J|GD2l!c%i1Bn5K+l73*kPj&}f^Z43SAfvK~~iaMSE`YdDNgJ&kKm zKP1bUqbBal7lEHE#=DB!-fD zIcch8s@Y*d_?IdfXp~2RfQEi)$0Gs7Vf=&U!$_VBc{F-=@?H~_E1n9SfIgsC%fta%Np!y# zBgRM--BW4#;4?@QYQe#R<_}ayG@(EYdJz?mp>JG)UE2=Y?_bnHx#cyZMrOmopoA;P zaxzvzEIqi|M#W7g)e?^l6gAgXh6v(E3=no{+g?-E9a0#eRebDB@tsuxct6>oonurn zb%?HN_&KGBIhAHXDC5Wl)WzG+NX0^Ebsaj|FVOH3&onC%3-lf7z)^;wwvmCdJz2F; zfM%+BW6+JN>%#chipK{e(nMaW-DSIw6ZPH- zlCI0VmQqob_}n1C=F=3QxBzwsjXvZ4Cb&DVeTfr7@Nt!F{k?CO`qHTg^ENsQA?yo} z53usou(VkWRS^lPF05*_=Vu-w0WNYOn3fPS;1+i|n(d^3()Osn}Oz$mHMk z!VcU5a^yvs%(R5X1LZ7_FIptBMvY$5TPy!5$*v8}A4+D)~aC0hyC|A_Jcd4kC*3>dNpOy?6 zXH`|TZk<1ggQX!k$tdd-BYn8)mjJZj#`@`sqz5!>fR(Oz-2lg(H|OgCiQgzD_R1Kr z?Ly8*+O(hQKjFm_QEDBLFg54HXsDV(O1zlU7mo(H`d-@*cc2BM-mO%UZY2Spk4ybI z!ESOo)9W^;-efkULkZuKAFKU@qykld;32B*6|`(RigfaNSqeh4#K*e!20c(@eGfya zu1A9M4{v;Ail`BEZ#U5LUoiCKA%0iW~jKnAn$K;+68|$H{^9iNPrtphO zRx;_1!(dQs8d4gs=|C0_)K>{|QNiDcV$-?y2od=*QP8A_25P8~WgJ6^bQ~sLF$>M{ zBTKOIus85wxU8o*h&mMj8e!v%klL|DmGutgoJ0b4{On;C7yQJ++CHxSJFmEJnbz^d+C7$>31)OWE)$`y{> z>0Ib+zL7N&78%sb&;`t!*l7$3nauc)B9JvSjtVM=ChxN|nc~>kWzq%gWk-1ADO)0z z43J1>9h4(lhjt)9z5eLI&PFp8pAgjzNrM2$|Bya4+?sY{3fS0X|uL2uBADFZgK?|l<)O(?VPP8`kV=+v9XD0zTc zicpYRv^QHcKFqQ3W9lqW!+pCBYB6s<3=_o>ib~qGBOcWY7X_E+wX}a?bURs3C-}7^ z&>Of$=hPkw_vB3B(NEkM9A*@ngn@nt-sfE=vFg&v?Y;s{kv>)#aH zIyAb3XQuy#qS`GEmW>8y$m%tdhccbjw=JtKg;;Zp!UMX&jT0o=$Y0E`1pe?0=T@ar zBBXO0v=88=l}rf*DoTd?)}uO84N(Mv3+4mr^6*>TfiP&4eH9B#=o<5x6*t zQ#2NB*&M2=^N$>4G>fX!*l99vrANI12qpsxo3oMl5Hm&)>P!0cDE-i;(2X^nce+u2 zEkh1GrGm7bq(YQ}gkq4l$jF0fPH!73mf7#rppk_TWWgk&J?3jFQS7DeL|J&;=|6dI zx4?EI1~}y3(sJ-+TJrR#2U^*VyVi6#7B2|kf7;NJc5^j#Rx4g- zwE(f!YJh7_zH2&Ze$Gb1F2<8ZF%cR1)OP4p0EGe8-ID2PJ8pi&Mo2$tRwDf>Ok#tv z#hLuW3FFa(AhV4av3NQrSQEZZMILHDK~P2EEMXG>spkd(E^`86h?Nv7oO+cBmMik5 z2(!s!Jc0B(R8ohL1$!*lZJ<=g5%L`wj!~8RbD3QsZlDBoXcFPtbT-QxdKyC+8p-|) z6cL*&nqv4vCJZ$RR@RshtAy;i*!a=pQ_WfuMK=cV?+k_OB!o89$BRqD9K0p43QF** zQl!Q{$Qlo##(TFVE(*Ihkkw=_`(#r1i?IS|lvp?*qXB!9Y+=Z=#}kUpS@4*9PD3hg z84#1IBYbE8YJDP~_y{2Hv9(xyI5283ohcIm*!rivzRG>%k7}gq>ynh@E?U7F&MDRE z(~0Xw8v>~uBJ4p8lxq5bZ#W^r_?}aUqE$&#Y>B8Lb)1p}ABv&Tpn&d8eclc$OBj~M zl^@&HfTILo^P2N z`qJ+@;4AU3@~xAj&AmBUuYZbaKG+XSI0xF0{WzIUlnW*x% zU<1IOkh#x^xb4h=ZFp8Qr>3i-#IrOvDl9d)x;7}l80{qj5jT$*(F&F1&V4vY6@rdZ z4As?a!*&~patmmp!r@48jyUFaUqko*&VJg3TiM6CCez83nu)Z8-B0!*? z!p7qu50f%P?4j1635>V;TdJiDb$F$s+}2MarXEU0f+~CD34GK2DrlyO-~zcukhAJkVNjl3aktEX|l9& zs!T>p*Z@)Ea z?$Tdy0h#q)Xr-B{y_40|at1xG9tYa-OJ+_tz$6D1#g$oTw~eI$Q6j1*MU_d2apy{6 zp9Zmx+5ASlQGo^RoAs0@;RBP(7wnizr=~KE(UgtP>ethMvLOta!m87l0iid$auQ$> zZ^kP9_Pu3mOT`*v2#g&AEH4A3XBZR=ru7gw7YFyEvmz!?@+JSuKt0ZzK{$ZTtGGr| zUG6X_pLW`%zr+hb3ykNvS|o(RBGRPX6nYutJoq>&prXV-DN8r&mu!ZoQ~sntq8h{_ z4Q4iwc01DO%}o){5E2Hr=bAW+4DFZ#XrW%n9am*KC4R7qC!$P)hzx~9gbol$7ov_F za>q6GSLHAMIFu8;Gif_mnI4V5dMTd zZ8eI{yopCTK_#Mic?DlPt5K9X1SF-68|u<9Hh#30<Y`0YMjkeE#W#H9kSopYoX^?laM;gUA|>u9yE5)C?d zBta~|WhZ$hXdo-6geN=gP6FQS4149w$-2aa_iVN{2Ga<)lJG##u#BJKp6EeY-Ijm( zLCA|*1;#RHgQ*FijcBoHO3FUifBzx^c8$)hpe#}*TP_4Jwn|2U$%@j-w+oZrA!;RA zL=tf8No<6g&<~rfLv8rM+BM1S*CLd@U7&xB^4PjAq>e;3kTLOUxYfMNDs@Tl6=+d`+50GdExQCb2hqq;*V6kXmyNyr`;*#-)X@*s>-z+tChU8{p$_@Wu6 zH~olJLVRwt*_nrxUdP}UL%XE$J!%R!?&J&<_z@TuU5(fZx$zAwW(%9VVRzm?o=Hs^ z5n*(;xwrbY`b_pX_EIfEoajkGEt?zGP+?ZIEzpWKQU;Sm1PD}Ey_sy;s55h)xC+H# z42Ts`i6P?JePpfj)H2S1BFE3ADzJLDl>D%Mi&o5t}-aek+Jqg9@Uk{hQ|M2+w`19HGhsVBqe80~` zTB!g3?BoB}!R^1-i8+7$_p>(-n2IPo6B+>)lfZrs5aO@|&dG&lj+97UZ|)@00czUp z>T|2Q=mTtyZD-RRWs9Xv@?X zLuYv0!rMvMEDz|55^;eqjHBc-uK3FXm8bF$5dU-Xx(ooE#S%o%^Z~5qo0Dwx0ws+u;&!Qd#q)^<`lWQn4C zd+HG>3_!<^;-@Gq58WUP*+yK1s+p_c*Qf)WK0_gkpUh@e`EUoxRpD!z<_DKACDe7Z&(!nUIxyDiQteRR$b0%XQ~l;{M`FeNu}~vA9X*yiy)1T zs!+Q+y@P4pR`bM&9>zqfwk0IkpA2vi63_rLUnaf4AAK~fW~{ixEK`H5(#kNVHkmBq zSGLYm;h7jlCLlm!@U4?Yrqnm1tt?zq7S|-&RuS8np~$*VDC$8myAUX^OsLqfAm|NT ztib*^YhD6nQb_HE4l`B0?yUkg*D$!m?j*Mk#Dj>xLSGgD-TRo+*3fgmpn$p;t;8#3UT@lU;UN z#pL+{6ZhI4CPlCok+u*@Ii;m6J1>HlsCHIyBJkWWnJTD?E7$7cz>B;i3()c)k3+TW zhFBMIU}{X`X+=QkC8SMjuu@i)PFZ6;MupjE=IwjX9c8=z^V6DvNC zT#8?s>M)XyEXG@PWP*dXWJ~tcDq~aV`g0Q?`+zZlj3+o=MT?mI8MIL#%CVP**w(d? z)+e4g5++DWFXRpb5bnz?v-AhOfGLP`rAJG0W7Cf5v+58BYJ5B#?CV<_)+k;45T!Es9m!B;$4ObC`uwHeHgPAS$pI)A zbR&y6u`x;VjMcJUV5jc216C(QHeMCyY7--ir=r=WdWYy2;~)`@ONwCcV8zv_W1(XY zuraQ)Tg49Ly$x~h+HW4fIjoP{JbgAteo#QKYkfgVauEDIXXuOGHIt@hIYFk~)5fBY+d;c?6fffZH80$%xsA+stX4vs==d#ziFAg$DJHSP@NcYiWWj z@dRaQ$SZEK^Ay;(_^#SO6~03Ta+bI|T&qaus-9?J%J~orHd4&aV4ymZw8B-mze2@_ zI0R)lDReX}sE10{vq>>cv7wA8y@GN~fp9w10yUAlM6nIpc^aSC$u|PPjMXX+qO6-H zCTqPO+=a_dESbgmyrLQHvpPi)JstUPgGuvynXbG9tx&GX=*#JDCqt# z4k~h!<>o}D+`4jS|MZji6N_9;;UU zV2^EHi9of+8(=|#19e0w9x7oA9{U z5F)Xx`mGMkKb%c1C(`6aTT$pRch(he2uN)yQN~Gvz#iHYerp+JAv7o%0lLEvbwk*M zQBeVyNVI_|uAmhRYVsYrwQ34a*;^L@L{%a#j%qiH3hJoG7I;@lQtb`N>N`^iRe@_{ zHwLIyffRK}FhHfX^#!P)iMUc{4)9#ju4{6?+=J&66ZpPf>v#C}>0K=^BbAWRB)K*hh7OP<}*5+-=7`qzG`4l3WWe zG&Py6q;V|p*m0&Cmt#85aZC1&(^ENW%luR^jM^k=8FNr2rHJ|!7yIbz^ zQ%5xHEm}Ya*`!Vo6?1mE;h3-!LM-Azefb`~W6(qHQK^*s&K`A~G9y$uXH+Dz1%atG zx2jTY%V9(>jz>0i?z|UxV4{*wDBP~TdX6OX6~3u5Nv|SRwmy`1RzRfla|5SF$j-$r zlj1;C1;vpbVrC;g2BbW^pX`y$MTWIP>@b$VX`Ze?gNg&yL)uAj7XO?iQHC68-1M#q z1eQb{xDzd5XpV=Rif(fUWt(MfK{|=@kW9}JBU1)<^x7bgF5xhO4XIGok!D|a-z z;Q7)=f93!&Y6cF4pju}DA<|;mBG2P#25P))DxuR%rGc)jsRnp^R;_N!A0X_U6TQSS zh>w1fJR8CDaBMeKhNnU!WC)cLO9KeO9?s!;^M!@Rmvb*~j=TT6h3hOl5R zO`vV1G!(fA_*3|1*%Vk)3>ECa0TM5vN0ExyArKL6Y7BMk3iU1rv6BrzRquGS%%bM0 z^9vCvLM=H4(y9HA=4B_X$#1B|lv$-q zo%<$BXBzpC*{Ue2?#1!!*^_yC`w>Mjv`HsVa)@0t17UH68f`F}gTfG;ZOtlyiJVmi zKM>#BthtxJ-RjAL=zka_!zXy;3zy8KVGUC-Ao8Qq1R=-)6jqh!q1GBu+fn)E=ZM9W-|PHjz_?; zm0kpkk1gprUCQ_Lnxt0;{6%#vvQ2a%W zFax`ox&#vaEgchUAPvjXXeWeLAz{i?8p48j-cZv+KNw*MXh`WQWt7a-oJJF(6`N(# zYBXybZ~_kD_9(WiDMlK`V2synIw}unvs+ZES$?3bv>Y~*gUtL{F>wyD4Ez;qS`f}f zN4ymo;dDF|A(oCO!NOxPX2?2l3U9GXveKY0U9T!x28-LB;5(!zpf03R^I|nym$?Fi zkx8O@@}0{Fh@zwr5@8#Y`vd~-;W5ZUzp;1+(Sc!i}S{bm+mY*<&9MD{JVqoAS8kh{I z@us2qTAgv67(-23+#ckwz60dx9gK06x9yU_eXqwdV3(Sqk)iKm*AQagF zk4U$Ivk8WF$8TUPZT1Yy3RcdmWQ)L<%+T1Tj9P>`tYnyLXw=znO4%`7+jK}oUtJQd zT3%fB{Bok30BPpAwsB0F~rw z*m(k9v@P0i$ROq#Pr;GpMx27I>KZ8vAkS3eXE8J=l$APmn|G32BxFa>;1B-Y#HPhy zR`{D@&d>v)>u#{E?@pdm66m8vf zbtLWO#@`Bn-YbI4L;H(GdQS{jNGT)+O#dXQ4Iv!g3h^Hr}XA7@N+{o7CYflmkEC&FBtp-4s!s5 zn>alCQgfzkqA}$+g#jqlnqkEk>P43z_@*`PbXJ1|v;a4VzO`#Fi*uE!3dnrdR`A#g z6yeJfXmh_w!nn$(L6e|3l(iBXGU8u;jfYf$lY{0(@mmGb^cE<5DWFwSdJfP)f~F*Z z3s3E+DmqaNO>Z<=0%lpbuse8}%6clA)TGoxXCRw?BN#+XP+Zj90;x34Rsa@I&4%eow*Tj_}ppw=ez$=^CC=1H1Td$9L zrKrT@JVs0)I%rwaeSl;Yn*wVw>Aj3~&_pR_8Gw-1^l#Uo{n>bhg(n28`Yc(ff({ht zg%+JUe}-AW;z>8^=f}_EqjT^Fdm*7k81#ldgf~qa}^tBscLwPiD@jn+TLV5C- zLKiFZ0$jSdCN2)_)cR5$1mOt_Y7pGKZ9&B_w(WB&Q9PVc&D)lc;1lX3tGV!g!=Y{g z0u_@q`dkH656L}1YEt@1b-`!Tkw$2w0SNQ5Ig4zuz=ajK9Pc%GBhJ-+EsJ8yAJ)=z zDX`)jh{fdgmHw%-oVNP)jm{?WR+`RQPbp3@Igds6;XsI)cEIaJ2W-klFGK3QC83&d z98^eh+*kLAzI%r4HB3bv_&$oj33U}|4hbg+jYWlwdLtrK833fE%wVT}v=9SCH&l(4 znd`JPMZx)Tf$Skz<~J(Dg+4>5JObG#*IY^S#NM*e&sNBj$ee|ZP)$N$*DA=s?r^Z@ zcaoeN06?~MI|}H*TwjZ(qtmb;kXMb%(^ht`Gq$~ctpyYCE0r}iSKkm2Zwf+hO*~=8 zY2S{7G`Cu>PLwM5M#L0h@Whn0lBudc7ejhe$}o%~hNr-hkBYL<3!NeCRrWR}m#H-qtwyRojG6Ui}{PRHcQW9<_Y zfrx7^0mWC)B9-q3%zDta z<&4%wj85fpMbyZxjfZ;wLsv=`+3-~OrrgptD3nb(6Hl~>kEC-0AxV@nSap=&AKw$q|h_PI=v zHY8;k1|9b`U8^1=N&1_Xxq1Dp|EnLKT5To}yBO(HvTZ zUM;5R+eZGl8yjYHRu$Xxv)h$T`IZI>kG^cnYA8yyh?@|Bia@4eHD~yMo5h8e#)KQz zpwAhtl)lPFSh%RMk4?+7z75JOEF(%7Hatisfxz~74Y7>xHI=e9uOYT^h&{0uf?6w< zVHf#~NO!8+7`(6}DD0(n^zG5uvZw};pIGVwC`WZXmQ{M}LcS|v$qt4*+gzQf zi5W8aY8c5aD9Y+po!BuE5n(!Siv_R}YRah2NQkywY2ks57t1f^h@;eh?PSdg97&dy zgqTdqp`X|nl67tpagw2&N&YTkW)ZnGBNzavH|Iv`)_MQNg+Rk6mT$mA+``3{S1{=y zkr%hd9Ee2a)U8@LchMvZaSmf}mFC%mpsWeR|0oiYt7@tvYZ+kR5ErGHlH@!qc0m=5D4JEQDC^rgS64NZvIfXtwC?B~ zFqKp3}9S2+HUuH`7p24neW%5)IGdg-DZADjHi00?;5PO{F0wxmDvHadXJb zB;Q5Z9Y703A*$Su`_w0;7UQ^;~T;P}#$id_# znPB}0Q{J>4K)=)FO+eTt*e&bWBA;u!40C!TvDk=e%mY`{oRN~1=|*`X6{RQvVJR@q zNW|C;G=|vo*|F!+vrzy^P#nchPJmSfsv@g2+ zVbDh;avIVbL+ryDa z=WwAJYTF^}D46Z4?)*fpr6LZRKR{*8pl%ceX1FIpReHRo#!POV%oj?hE`+@*4RuV; z%?>$>HFHT333r4$>8L+;DU{-M}8k1+2ktA# zmsPRdr=H+g%Q6PfNcD;>;*%eIN}Ui<&1SrfQ!h5b0sQ4-kmx8LDB2BBYQVxhxNtV*Wwi#hqrRYE+QaNxXs4Vo2&OBpM-wq0P zV_BT9+O&OX4*#^#7(z(FNLiy|h7lcWML`qihw~g7w?T!hAa#k=0EU?rAc%@*?nY>M zP9j$i7cF7jh7OHp0Kaz~vZaiz-5@J&PWFVT?pBB*v}VVVlQ3te#4ZVyV1lk{p^Jt? zs^zqh=%XFsU4_?FnaKG;P2#H_mb;gUwW@ydefC_r3k$uVtAQuiRK7_VybuLA>-~`+ zr{wDGDhZJYM=r7vj|l`4H-XBm+m*6V@rgh-9Sj-o8hTh$CxkWCZImdv35aYA2SD1# z$WU(bb1EVLH&k#!*cCvBHA1xaB*DK}clC!L9VF2pdXVB=DBh7HCHP}vg&@DlBF^*I zlx9l<@4iA|)nr5jNey9|jpZ|VBDj$kgr>CVl?e7*B~lVC+oDe;ws#n4H8zQ;&XkWpy^xZ2COG<=a=D3oY;R)lrm7)oH#NZdvQke~AF7KKs) zn*<0b2-kZxp>1H<`fIPGQ_)EUrg90)3#cvt4@!{#pjGzEkyU)sjO=oOGS?eo`v)3O zwT$QTEOn6(l$OXWy9ifetz2A(PLQM#FwU$C^l?M1h82ydQ*Ah8lY>VdhJ=bqWa84S zK#+)HGs>z4hcxT3VJsBdx+T~GwSuB`R1dz@Bp$I@gDQ>?AZ$W~h^lgO8ORTZx5`ED?#XTryg~SXZj{e9?hQ z5asd?wpx)~Dsp$5^lJ?28*E-yF{5>9Rr0kI;6^U zYc;@fNCLkE`PonCm#-MvE}ID}7RcvyBR|HMR?~Kmw0jzbi5u|yhhM0zld42|o+v~E zxN-=FX^O>zjEnFjg4u&B&hnJPIG_I$iPON2x6KdWcI{S4VjiGYefbmvVhN% zM=4is$+XmX81?aY-HYOrb+^M$19uo}nByGsjuN{G-!zi(?GqBHEOB!x5^Bg>Vd2eYq`m^iDrn6Y0nRmq5}))1AEw`wGY6L>4+ z2#}$=lQO#&mZofF*m7}~OB3g;ria6MJGUv+5f2q#RprA%kaY@#?!_E-@3zRhj}0EO zSiVKF&1aLz33dEMg_J`j!k|PN7RH3!LrJr6eyuW2JSEr9OiEnXkdV3Li0Zt0U>cMP z)#Y*(!qWU8=ZqX(pc`-#b0+Hw+#l=oq#MgvPIQHn6|?8YVQc~pwxF5P(p(1JvTY=OLJi)T$Z45_}7CytmU;2_}400=q*-GIoA*rd<8O)0pk zJe3A2E}=vPGKcT+#5RkoT2w(Y?veggF1F|FPz|P20aoU}ZWs-Fh~wCCWv0ZNaymKF zLm{%+>LK5awtGvN!a;JD&n*}jfz03e*+rsRU8$2zDMT3-B5CpIrDY8#kz$B##I2It zdoXmK+O{=ZpPD-rbXnP9dQ9dZG<&Y=T*2w*000S8*yX&2bJsDj2fbKAm=?`!2))be zo(WNv*w56=QXZ3Cka)&5a4IjEgZK2;DHsi|RAiZtcBhaWkg6^lz4dUnKvy@Q2S1LA zH=s|wJ75vPl5|TJNqjtt(pAtF0&uynTZO?07`Jff&`}7KztReBj+okuIk}T?OdM9N z0_3FEGx`bVg~2)uYp#Ei~=TK0+sB65JiZdp&YVz%VqYLLm<#6Sh%C`+Mh|7kib(MD=8EV`IuWE$C{?OwdA zjHb>)ryY`4^q!VLs;}*TrI5>=(1z0N5px>+v*fCMwbo6A_bBy&Vws6$;S8en{EN4T;x z>_aVNJ8*;h`)w9iU^-0X!p75DrQR^gaSA3IkznG0SRgvp7mLP9NDzhvC$m>_I#}Z& zg6T{gBQW_8_|>ze1VZNc**vdM+J_TD2v)C$D;BPxkiLNT6};t4`Q#eZm@G-9yx9_m ztj{D2bUSO(D8Ta_Eh|POtezsNJKz)$0B=T=J+cEPG+y>>9Tk)@cfbMhV^cu_g&gKW z3!oNOuJt6=W4~m{Aqf_?ag^HY`uhA*ow29X%`{}{1Axy9G@Zm`XscSxd}~-%1+?D! z$^p%LOo;(2g(5adq@T!wiG`>$lgzYZ;H(-zii;vin-mGB@MPyze5A}CR8+}0;!$&J zP^r&gSj!3>bdPzE2>^&()V)+`UlbH~qocDqSa9r+mYZW8NQ%Gb%-U9t45Fils-?1& zrA90jZZB;h*52|!*&*{5IU?Pulvql-?pAE96SRqQU?1m+dLyh_qv}D(;~YV2x=Cgj zbUNX&PN|tE)=q&pGC3W=Cy?Tg+5~Jbt6Uk`vO$B&NHWe(P8%FiE1*`h5V;p(AWSz< zUX#c?Ac02*plt=Ag92?@WnM04H$#-=-=qI~THzh7e(mwG7B?!DVomm_(^q=}~MKL2!-p9KZUd`eNnU6bkU|RrTU733lcX<^d<1 z;jI?Y8kS>f949sdSUk~tHvUPmXaCv{0%avijnG4Ow%(r-^GGVOL(<&c|ZuEtb9ZfjmaE53MNU!!HE=2GZ#vj z5msi^2Z&OL@cv`eaVp>VZMNUj~D@-mm7Jf(ymU7+_x* z>jf90Q|k$|)<_OR7ljV?naF(|~%-h}H&6=w)99hc!b ztEdAKr4CUj^jxPf+H%uWpv!iezTj1Oi_kicC)aCH#^v!YZg`ltdS4x4Q$ z)@+TgIdLQL4k;p)XVW%$a2Jq6a)v6vGqIU&%+ExD4NQ5YZ1E%Y?&PY0M6$3~U23uh zv8YG>VqPZY)FB!lI!Y)3FeR&2g@^PhKMyQgG^tsnV;C$F38yZcnj2i(&`@%#G5fdU zI#acU5w{U_&9&Dnp*}Q$GVv1d!&YgmC>*YKrh1d=O!G#DwGCPMAg5dvsbi~ow~2;X zW9~vih#xRL#4ltn1Rf`oOUxP~ICLi2i; zGbbMGTnN7pGiKRE_!G0rxtAuQDJl3cUaC75dJ6)VV}i6pPZnCl@LEj(J7uPxQLnlM zDL>XyOO?yxBqfF#JG>B{n~_x-L@}x)p$G%fQ(4g!^=(##W)GWA0(GEAm}rm6P%}V= z5_QCGEmTEzoSXKX0N4?DwP~ngO z=(PkWkc*nO_!tbLn%Z<819{Xkaax|HEX}V}mBLYJM9X(HEbZ_p_2g*n(i73M=r>ny zSA4we4@JNHm6U$H!oKX%0YXqBtV;8@(ipX_ zm+=hb0I@0$dljkZy?LCYr5zZ?87tlT(>4w>T%l?dm6RO|r~rKh&BGv&8zI1!e$Flx zvZuf+IEsRe%aHS`JlKa@7E55IZt9Qn$I;maSjUc%;%E#5naq~NGX7T5(+6IN;bw$F z38aYAO8DzO87j0=6Q{g>JT@&6<9{6;x9&W2jm#4GKLC6 zNBzVO(~FRXMljD6@!+FcEH6VGgbk?79D8$nmpN1NDWg0ZQgeeU7uzbxS!@l0gm95m z&XUouG~t`@B9?)txg>6KOh>BfQdkkj^0TFIsF;+nr}zHGy^WODUo(34LJaL6*)$%8 zZX0vf95((y7ZIZh#~)zr4|dwHWhL3$CeBW_Pkz#^5CExlsfx4RR|4gPHW_&<`3l9kc&k|6 zt49~T1|DyOQdG>Va6m zi<>XAH#A(`DgR&xVG(eC&VtckwI0u)uwXG$CwP29<9`b{3R5pi-D|TXK@IYJafYBJ zd^t32fV_4b1rrSDko*ZhZy|a~jfZD6<{&T$VN*bjdL7(!s-c8?lXUmiMYl$#CPym@ zO_r=nMbKI$?jS(oXr3BfSV5LNi{Pk#BEDNd;3{44?2=Q)0WOO2@Yg)l`Dytag(8S-PNv`cTNmB~kN^)*J zGM|sYvT*1>#HU#j+R=q7XUT;rSjb6IM{%}EsWl`+BwU{f9lsFq2w!7=t5OmAMr*N_ zVDh~U;v}W4MIZLwZ=6sajye5NY|*opr&kWn)Z3H>%<_X9Ft5{Ke4-#e+)8fIUahYf z&#XYdAPRQibGRrT#EV~J-5@3{P-9gYYs?&KoigP46O>bM$ID_k4lN9AP9szOW?7yn ziOF3eHX?xUGsW;h&KsC7waPUv;YioG8>N7_NJX=9(W?O5lz5X=Mxx)n$cOb();2_R zk5MeqMYb-XDfyn6_;Tm)opFjAJzD+Bs|X-D9I0T{o~Mrh8o~L)ib9$-A+azYqY~Xt#GgHFV7$nmH zxI7~`IjsLWQmwcrLr~VkmTNkqSImTe2{MSMOXW_^fdZIZ(7?D}7aEaVAxx-=9T1Qa zb>TyNBLZ9mL#S9af+E)#1KeF|_s*@*!4xaz)JDrrU~_0cxs==$Iv_ObGGMj;_J9K% zh?l7iB9bDfHi$^|X>vF&nhU~(QW! zhTG*b#%p4P&1N>OvO#z2v#|%pu4cd}6QaZ^F`$*@*(UsDbwa2y4wwJrHCp(C}MxE87yB zqqe8oq3Rz7@;q4{rxzjc6tQHbw{iv7Poi!D%taJ18>+b{PrN%*%eyvwQ7?^24V4l1y8_EGInCkyDWc4yGCN4X4Yeh`w&<}978@NB z^+p&VhBa&%b!H6vZHR8SDOaR^Y7?=Dy49QaKu2~w_1VeGsY;%M0Ziwv{8OHY8JJZB z`*PzxnUou3>6_ZHoL#Y3%rn&ZlyS{GSKew`F~^Doh~NehQ3O_zX#$ZUbeSkZU+?Z9 z&ejuHyQT`~n*29U2mQ6A5XFE|fwBXafNlvclh4YD!JPF&orpMF&V+Gl@>3E-cVpY$ zof74>XYQ^s7DaAaIe08|pfovE)ie*98h&|%y~?$ppfRyT#a4+m6h@6XG}#W^QDJ5U za5wg}NFyf+FT608No`tKfhk&uR$ATQGT7xz!bN~Cf%yZR!AU|}HqT}dper(Wq*VU^ zu_!|%nz!Zzgt&R}8|EFD2n#3@Z#lD)Q$YS0eVP6RL{mWq7%>ZCarq=9TEo-u8R zQ5>=i%20p}d?TCcqI$4(*^+Slv>8R-+(|I$W;`|47KR3r#Q7*1^-}*f|5$b%Gc6F$ zW}?xbo%a(*q8cPJ>{CNaikvN>gaX@Q~&RU)+zsqT_d7AEULC1g^%`q{1| zCeg;Hiiq-}wy7+8LDfl;JMkj{_o#-Kas|9R1KBc9ux%Ybk|k@68=I}V)pPLzWUzWp z&qhi#Y}7I+CphFZQqLt)Q~^p=2!2eY7V!m2qiFRUfFxvc1+vvgSYlDmuU;^+`ts zq&@G&7e~!a<)CVZ$c`wgqP<+kLiIMV&&)Mp;&tuIfLDO> zfT>`D4-!+7oaJf*c*uEtUqvP=)@x)Ws@yD1M4zx-kFClCpZLhMMo!|^2_i|bl@}z# zvBw#hUPNWti6sUSK&GzDc~lHS6=}yz;q%t(gc>L1r7FfehSX54R3Z!16cXHIE=h=X zv1;yIg;28Iz5+;FoKM3_PMl|fT(RlRvoP@h4GKlFu>qQrrE1whV*lm<>Pr$-3LZEa zA~_(ZSXCLc;~o{OpIGm3c&E-ssL5mx~ z_AyX|mda<9ka0;c&c&+sFMyT-$2<>1uC@Y0Jd##`ymFeAM~Xt35v^T^U>uup&uiFQ zitm3o0!zxH6Ja!|t*wCoUUzgyJl!M{aMV9NLSd^9^G-(z8=~EiLx8X~_A3skhEnh$ z@Q=kymM}?b8X@O29OCFXA?_`iBFhBuRtV(UUj$U&VXjc4irJtbRZ5Yh8_ju!c6x;h z7C?#j91>^&gST{~_?Ck&f&k~hjje#wHX|t+YL-t916CbV@W4HFLmjBqxh~LYZNbTG zHhKd&kGP`2fcVkbDOYIrEK4+hA@#$nZNn~BlD0sD1i+)t)CVmKJgH{AT$6*o#1Kdn zYx~;(F%7{xk|x6d5GFVmPD{>wr-ZU_fUL%K3^<^cr>UL4s7W2rCTQU2@3b>x=5cAX zHN&MfNLj8T6Ik1XoSP-#`LhnZ#Rki~U!W~M^DLuQ1K{@Jag*=wh zp@0bXj$yliZn&^}l?z~Gd4xg+9Yo~}D5}dN2_Xo#YgtC~PSs5b@+B;(&=X3~vKU^b`5amCRJU2iIC7zz&XOyg2#21ox<#mREH zXO1yX>g)(jgasCT;t^1)_Y^^N=g-bh9mHJZk=I%x(H!T9H5pa`VBI_jqDhMot5L~e zIKe&TP>Qz6haf)n#yzoPlIZke;EWYouGPo3=V#qKRaA_PRe~v0fTg@b6lM28sghFy z)cuGb%auV`7Vmab5AOO}_nMA0u}~)|4vb7GnatVkK(%oK=|T@4(eSfDX!eRNarTZS zUG4`)yYfe3YzL8rlYv;qBQ!K0C(UY8|I$n#vR81K?o>}yteQY@m%hyn3SoAvN)sCJ z$+s~#9wDQx#r1Obrl4JitXwV1RES=eF?R8GM2OpH&{ zv)?8yMH5Id0|!G^UFu63tY0-QKv%Pjkd85c-`zfg^GsF(l!=uU z`|}~uHCj|h9h|979MUiwz?TRPrqn~6MB4o&)S{enMwE6J51{2*WU)qkR#Xyw0lALO zJ@y_Tq9Xk;0-~G(+7%UD2DAV(_h~1KxpP1`uI@Jrqz4#;1UINtY*XcMe)(P);72Q< z%%c=rlw+weM;Qq>?oj=552yBooY{kBa1p$~*lq5VKT_8fh}EQ~GfAbSCQ;Y`8gQT< zrM}P(0Kcd7B}gz46>apYPV643*guhGkJM^D+?Y0Y0#4~hpp1k3Bi&qHyTOCPXya9d z?SQAPkqe5WPg5U`Tv5PJ%~$-MdePiF6AFJQmG@CMIL>C% zQt_$i(P2IVB|C|_Ol4P(iGegJU)0OQ@%j|a$w9KrIEC#aSK+TVRf(N3L@B5sMm-y} zBA1|4Gk}R~G58?_yNI!4cK#7FP?BI%z-&i~!A)xGhSJuZpVHa{R7ymKF#g1VI2Ib2 zDM4rErpBsWsWy1+ZEj;f$rK;LZmU`^c+LVfywfHlwu?iPVxMNRdS(?0?v{=v1sZRQ zTa#lf0cSZ1R8bRV$pqDH?W11|phc<`OmVkdW$G1nGUNLD|AmOT5L4oO9VN=muxp-< zx`bbvn;1k{ZG_yrfurfy5#Sf7vJaltZy+H4gc1=czzY$gT_z6z>#W2JV3Ym?ynk|Sq#R?qE4;u;n8?{# z&c=Jk)#ihyJvSUSzKE{+&1DSX(N^_D&POS#J1SKVSl@)g5?Y={UF6Yv28o!!x*D30 ziCj;(WTkb7b%mLTC?1h%>LFFO6hUG<7_n%jOjZ1Z9@2D-PjX3Wevq+dQ~a6ApU@SlDKVvA#+n43faYb9s2Cc_w-wJ&=O5c&iM^%$i3y zDf*58AhTNE&GJ##YWoB)aK{=j6DE>)#R#QFIL9PJWdkkT%uVmkR`yPhNqX@j=O_aP%S0)S4| z8!hCMDq9fN^GuaA%+->lPQpXSbyW?1>+e0e5-bT)kzCFc`7nVRKa%C+I_t=-!vLXA}W+hC2yu>}+qj(T4a zM|ftR`N1R9lo~@_G`Dv*ozAVprjJOP$Kb76f2a2jwBAp9K+85q>)oujO89dF^wTpM z70{hjL71JX0aIuZ9``09_O-Sfi-3a_;0KuKPuDiS06!&=JLyXWo5POce9si*QPo*Z zS7rji)b5~1XHbPe&`2j85^Q0J;1oA`Qr`r{rS?}oTQOx~x7#D)Pt@I*$SThc(2Eq1 z)4%qDLqcxW=$T+D?qJMy+FoReDs2d}jM8&6T%X&NUH(%Y?F50S2qS7ol(rTIVRP@LE`F~j+OuMl#C%~=wEKn6_1eJ#1APAja9S& zeyXy*!XxT5$VyItx&jIhP|w4HHG$>LYI%4;UPRrAgs2G#2&>2j1Lec~BoWQq3a+^1 z`uw-U$|jOz-`tB`d$rXs!N`E~urcz~U+Bl7>OYH@J%UU|up(T>p&76A0MaSNE@sHO zf*AUWxmw#$l{Ak7a*<2Cw8=Fwbfsnmn6ZEl9E&VCiHqX2+RYlNTF1g$$El3#(|J|B z4rIqXS*Sd;Lu04-U%=o3--sVd!!9mj_H)lpqTmzYJTqxS=`A+0WM4{y0^p%n z5kZ&rFG{)@Y}^^?MVc<+>dQL_MzQP^14s41AoIq>BQ@x=akz0*^(sVFf925p(Pr?6 zJDHu_w)F5=GKnXJ7dg77&aDnlESwUl)EVM^rqof@P=bzoqDCBG3%!oZ3Hcn?hwvt2 zwb7fQiBT}G1Mo!X0@|P=wdFKpM23J{;M8cz%Izn`?%{82v)`%0zZvDKN@<{{1i+~v zm2k;`V|id5N`AHw37yVC;w8Es2rNVd>&Ei_hI0Ar&Mbxv$BtD8f{7;@Y{*h?QiCp0 zhZ-l`+>0v`<4h1dVVdgW8vmIQ)a{=jRPe!=E%Yn_5=WJK?IFNzf4XeC=XT4QGjjd#aSDW7APE6Ec;KC zPbe8DX1m`QsI1crU{{=GI#C04gOR9IwA@z*76e8$35vV(qWa(1zg1RLwgd>=3^XbV z`?X{K46GzY?K++ZfQln4J=VZZr~m_w>6#gNtfw|wCs#01^c{w>r0L`qDu+y`vmd@e zZmbLHtR$+;cnfTnFXn1kP(R=aoEgf(vvttWEOORbER{+%xxTXcP>`PIJ{j|sOGP!g z3lbWDAP*G5hnN#0#9RX71WAw>@DP%kE6G<~9THlkJ+BasZ3zv^aL2DvkbDtvN&k^= z0E%at8u_eO32YSST09!oW#1Fhq_8;|pbML%0aL$9qZ~?`e^kGZXPc1;hQQa-A9Q1z zCMb*=+KF*&PgF=$^LZNqCJU%uVGt!Z)R4MIIN`UOXzO5aaUw%OL?nPXhdSV<;4vlP zcKS2~Ads0_TGzY_H-=otuswSNC^ab!EdsKbAmveiB?j%`7`cI95rzB>D#Tf}6L0I| z{=6zgARLvKWhS{bHtwmBv^;3X4>Df22p9tzP2oTAqc*Ttf9$dlC5|A3p3sHcK>(95 zkiK>zYXf{tl0>t8j;joMQ^3YKm*GfPxO< z7DNj(YP7?a*?!3sdp;So4Vxi@diEd?zqTD563YYt=} zvp}^HB7+1xW1;bvKVU@$fXU4|wpB`;Q*BSPQH`B2Og>PkEMz`%0vGj)B^(!iQy=%i zb}zQlAi+#d#IE)uN%AG2%LxkIU|Oz-UqtAPyj;_J1ze#?5x#Vmu%1r@g7ye9R*p67 z3aik#W+J_uvm3!$7b{i0sax@eY;h%VK*T;EUpbLcm1kc>$}Ek_y27Js-#xw5_&K;b zp`JBgA$|xFmO}^4W85n!TX!hFg;BYy1P>uBNK$OzG)u5lOpgJTf zQxJ&z6Rg*p!I=ZWq*JMs+(J9tSjA>5e~EI~MzXajfFpzc?RB4mXa0IUk4PgP&%qZ+ zYu;HEgoI`_A_nE;q?S}Pp&{-RUXdl7)yx!M7Y*_{juyecX{PQvX8~&1fztU17)z<7 zD_>NmL9qxhv6fUA%6n5#16&cxs<5iMymziae5)oO0<*KSB6S}`zade^9jm4D9xGld zRz7U?)C$9?$L0r$f}23?el~AyaGoAFZ;bjk(-1Z>H8HMhai8oeMUvB-FmkX$Rv-}` zECD)MPufGS?PNT`$;0;wCn)(;0*Z~e+Bz5Kw)98DfevulQ{3Dk5rcS&15`mL{j7yl zdV;TvY*a)6J>)w9L?PzpTLOjn*w_q4g2R6qg_Jeo%U zRwU5dNd?7nCq$Tnu~uevhdH2KWaqC<m3T z0#C_}*p{_43q&Hzi<^4qsIsj`JZNrOGQwh2Sz$63(buC{jr$49SqxAo^B7HqDz2t5 ziWGa~m8kq$frwA|L<_Ig#j1!KD*jo5_*fb1}eU+5aam0c2z^Bb}%GCEE=K!J0N97prKzV z$cEO3san!1obcsJ%fG6f{{8&o(VU8LE~1v8zJ?W0WtQU-;JIZBJ>kyo&@Tn%v02ec#>p$K6L zkzTKOET(3Q-Y#>TuD14D|++-K~5w+$Ov@iy>FYrLPR;>St;^ItoAZ$W0(aK$V zYSa8m&f{WQ-9~9tBKV5GsewuIdY267pldYuDWZ{BZ=OmhY9%e4NT`Dd`9iFIXp<=5I{5Nu!RrQz8QHrHCN6GbHoory)XE&OWTeuPmGv<9L8ch-Q_l6~6- z0|)O%@bN!57m`MrjqZulx>w}w(EgRC_I;jLGh7T`WZ(Pfu(>NZ}Jf_Y5WSNrI%RmY7{jAA>K)lpr8J;K$3rtysd6 zLIKSt#!w*gR_lb$scfL99?mUtR?Ehp;4BUipHr?pYPyua=iM``u!5rkVTjIK>xbdn zl?I=^epRljDAagJh6zuq8L=(fj?d&lw%#WuRjS-)m5axf#JwF3T9z=pQC%I*=E!!M zrL<&MoSOz3Tx7qIG2(%(Y;|+^s#hFbBsP*BZS+Fca`Au=Hs$t_u-Jk`Lx;NVgp!o~ z>@@;<6!41Ke!>A);Bm<%CT%7+b&*(C;a;@bWODoCYY-V3&XAAZvj*r&=o(Js+EhlJ zW`lFv!f-`Ll*pjX?PKM#k9$l($`R$JZm{s*D4k`5yLq6aArY@AXV zNPl=zAh{{*lIx}iZe!ADf)rQlh>xzwojX8ZEdmwlMO(FGRX4j_am1_+0i5ZI6T2e1 z0=8x?O%*D}sxL-$Hi*He0IA?DTYr^Uk})S&glM$lY|?Y{4Y9GT1eGEsoqMDTx#WIX zL;$l%s7(r#Z%wFzQiVL8v7vKVS#uy0k%m?3fo-1yuZoEa@vi#hfk{yyHmRt96+UXq zGT{Osqhr)0Uc{6_J-fmdgKVBI5j2YcegYs2CGvQuZj}0TE}lkydi`RDYw$BeO;PQp zv)2&dW^n2?GdXCESB&LPjkk>WD|dHGUT?ITiD3I2cww_2)rwc?g7aBOeKs??Na`?YINZ7V;0ZW=3onp(l)(_ zO5N$S*3U1ZCCkVcrdb0GwiF*3VIoh0GoNGMYx%I&u%Sae&--MB0TRt_PoHI;nq#rh1J}9f9-3IP4%k->@J}DIEZ*h-?@35WF*0 zP-}K<(dEu5yTF+<%i}_dbfRn4nRUzIia`voP1M;%biRQRC4PR_0ksNrs{YeBVecxa za-A6}!x|74+lx7Z$UXxXwyWWRL^z<`^achys%nWxc%-IGNnF%t8IB@S#u*r1^MpHS zJ_H+;xl+T^Tg*Fd&+{qj82O(BVq0-}%$Rt>rCx4A)mW+qU`8VTAeAx8^-1WwfKsd-*$L9psR1FD)Q z(cmM3$cRg{Q)P=W`i}n zfx&W}+#=i;IR9W?iU&Xlh1S(uK%wN~X_=hfmU!~fNFn|gpQzTxUBjnQs7Bm^E_C>! zHi&i0Vi#rfgFEsG@)`qeZNYc5vN!k*HQMG++z7Dm*S zg%m2O;EY;xGja<*0Hnq%uDy=|XR#+Sm@5kLxo}EslF@Jplu|x^lG4Tt%!agxp)rks zNXTqRLrLFDQo1N<1cUYPmkf0?;&yeNh-i`Dy2!Yi^+je$jB@~z!@5`5i{EB!HVA~o zGh}6VOYWzGg2`P zuEaHVqG{~6qi$K7vt;H%$jGl6;rpaZt%&9nUm;6cmBrIbx<^(PX#&lY(22F$RQbh3 z-qXv{8?)0VXW>KD0To4t4LoF_fI15w7_GIj90wc~z5a}Bk%9aKO?37dY0b^#Nr!Zwz!1}GPU$5$hBr_ztu zd?txokhJKa1{=qN4}@VH1y~yv9k&TiKpvX4^fFJ8_IR}oh&!cl15RTOrB+7`o~ozO z2XWx9>NO>vh>#XRwX|#Gh-Ai|9>Ykk%eK(OvV7p1BuK^tONqF@=r%i)2T)!yz(>f9 z^%5|;L2cl(Hz7W5giO2qVDq}Aw9g}%A6zF`L>FK(-V~dHGmZ9?X9RWZhTVlbujuT~ z#SCC^DCv;|EUe{%2&DrNr3{R}0$rLcCy5AMuFxv8rU;3HrF{uS^YB%sbBlrFxH}&c z4Wc+W$$F_IuE{ntAvT?`-V8afs4uFG&hD7p#p0Q-n)v4Nh(qkr!8+}lk8%oM5{2EO zXi=~HBpf?KuVV0MWgt3bWxkGai7;R!_-0vb3w$V!OXUp5H?HW3(&J0;EV{BNZnig& zc&NckJ}R4INkqWpp*#OAwREjfT0@8Iup>A#{z#LukhMoxSdGduj`vr_S@mEo-nuAD zshpo41_w`xt!>mkWw&t=*J_Ip-F%`~5gYI;wj7idF;za1n-&MPRCA@_j_HLLr%R}E zWW4w-?$yt3fD8542pd&!8DX(1mK4V|;i=MXA@@RKs%V^NZ2-rJ*t1>&nE8fjCI(f3 zZoqw_6lP(o0hI;w?06{C96h7?ny0E*hTw!2L<{A^fzSf(P&rK&vcVKBGm`^0fs6wj zM0izq_J*E;y|^h&5mTaA!){SSA{^UzY=xr~>S>fgW$oBD+mTR4B(%8zN)qNEYC%Rw z_Og}O&`vVB`3d1JXpPM5n0%yfN~@-;u2(Twg$DF%1H*-^z>m-fgi|21+#rzR<|=8` zt~5#zAdA<8uHz`0x|`lRas5bu3mJCu`&yt{qiqWW!1q;=~UE8DW80$mu_2^=1DT~Z>15~cm9 zrFI@UnYY7EsSz~09*rn11p@oZiF&%)Qzaa>QhtsPU}6AAu`?IKUq%~91EQdcmvVw8 zWhMTejOMfxLSp40BBwUxX{x_YIv?6>Ch2Vv8|PK(g=8HeOEqRID5x8N`X#I?xynWy z_Kh=uIl98nN-GtsXhn?n#fT0@NxRm}T-K867Iq9?=EO6Y*k6Se^5nVq`i%^52`zEP zV5)K91v=4Qi`i3e$fFHWwS_TcRHC0z#LIT@bQw>NgVc($?h8?vgGCgan)2{K`qb}l z#(z0#=7|kK0Ir};c?Eo{qXVl_>AWeGEVPjKjfIqWNbMWCF+{ZQ{rNF|e=FRm+UaIbl*Kru`j(Y%H6g4lj-6uCMC zgy}I7_+IT%|Asu$pg4&pVYYeQaLy(BCjQZl=enpClQ9*M+I-M}t6n*3A2igfC>Ne8+~x z=vG_EAFD5jlWRE>qVC57;D865tZ1lm0f7M(7%1cc>$)B1LNCf|T;3)9AFHg{!83>M zYk(rY(C#u^o3RX)j?RG~seIJfDZ;cMauxeVXc-)gU#U5)bGA|=KGa0iYCiMKA;Vi& z{0GraLn3Le0Cb+Ak-w1uNJCH*5iFR1tVqXKEzJ|~0~6PnD3YbxB`I}J9puhG&VWSh zBl73wDY|evq~<`JOFSUjZ4NVfzxKhThH4h638 zhIOF8pD{K5tomgJ5k?=)ov;TVRkH&_WVaYA%3@vP;93hgVC5r}Z5OIhcB8R|skkq8h>i%wT8crq>wV`JDpDJ&=}k2GaOK?gq=e5P=Ai`CBgGoXJV{-ESf<7I>o?E? zXTJ9&$pVduTdo2pt%Vi=h;J|(%>*ilEjuDn&5Na?^5lY-iz**{6LAVBHh%-gToG3Z zC-wmm{a>3LQVrw@^Gc)?)qrMPnzkds-iP=gY&Ce1R^VJ;AKqosF10~2Zs(pTGYp2h z%;se{dhMs8^Kvi=U=>W7QaDSMYXcEPR-BSpIOG@J^Ljm(bu$mB1Yv_*ZdjRJqeIPz z6k`8p{letA&gcSRC%2h&aH?s|{NNi1$pNnt5eR{Cy3CMgfw9n5qAp0ljT0mVBmg=q zUb0xDO+F(CP@!C+Opjvw%z+}D5ww8w)*i!Tih-q|f?BDD`UHnx^M|qHXHjWjRD)bv z+#(1y7OocLnjA!sLz5(c1|?_{aMhR($dwUrwW`o-`en}e1Z^eCF?vT)HaXJhRhi2h z9n9ldDYd{CB&FT~DOsvAH0`2rVSDUalwe=|Y&hXAs08F%DKx-^0%~1sT)A-s#jjbQ zE(xu0AP6z%UzM9fskd`@95mp&+5FxnwaaW)(&T4y0jMBQqnI(- ztlG!2Ct9#%OQ?jm^RPNHKXcZ;>ep9jc*lg?5CS=7|lpJp<;3X^@s+dK;I`7Nu9vM0Xu{v z^98I~aG{P=2~){WFf-)H6=XOyIKULj+aY#yj}J2rkV*oo6{>0L9#`cn4X3ZbZS-Qr zg8`&|W@9J$sW&X|37luJ4NOo>Ze{)v^CGMqmfV4cIP{PK(E=3 zFo~f&Sc?mxCyImxZ$Q|wksZuKjw>A`1_R);Dt4g-L|Z6C-FrDO?t z4bP3@B?+_;puDJnf@>cb1cjuIJ}XgWVqg^M-d3t>p$+1CIVy-b96K-u0HyCL^7%GXbI&S>H_PGm|4PhccGxnlty`n6GF2=B1S3M}D09^+a6NzEWt6kNi zWDaW08BvDX03o+Le#OeLXkVNy#o?rCQNV?zLB&)wNJA#Dx;>U-M|c)dg-$ z4Y7!+*&&Y0i@Rf@nca0mj#rdMLGEf%Im2LLhGUR{_%f{l1QPR*C1uu>0}maZoU^PE z7Ir{umfQA?$_N5S66onv|zNA{UAA z2T`tfwvfmPsq1JX;5tBV#J{sUlC4-fQSOI?sBCsOfFc3p58O>#k}z;7Uy#ycQVd8_ zX#!v&8OhYD9(U28{uYDqLYva+MJm7wRDJmV+Vv3J7}$SJYs*mW)_At^+aa z{;B&0Rd=QPsF$>WzwE?QHLulZ22k>Bgl=P5tJl0M`D#{|p#sw)SfkM(t5nH-BP!dR zqE?6~K`m{#!B*RMT|^x)%+(+}zBA_TZD39fw5UxAtH)_JE!K5X_@^iv1l4jQvV2n% zO9LE5QMsp%owV3CWs`Y0W_qxb?Byw8rOg1MU5d|qQR*V(x!!&%P@+$4?W$HuMR7LN zlia{IlxuNu7RZCkEN*=vekbB}Ga2|o!z(&I+EV#ZBbrG}Juk*d9~BiHl_VJTnddaf z7U+8C^j0*O2s%_pqw4*+)nMPHgr1m}R#*fI_jL3+j9PUc)f$3+<1vyyONEKtmAzmo z#UozowH^#4L5}14P$5D!k@h2@DiWS1PPu`O85zTJ9twHa2u40W0M^W6v{Lh*XW^dM zFA}Pp)(=EXi&w<$lZe278g>L8URTATg^5Y?1QyB?zzJ0r>eUGxs|Ub#8k7pGsUeGL zabB>J1|B70JISr>ka2t^Gi*RY-(*R`6&_T9XL!SC;z6UkPHj@x96%;kMU-~BKO%gJ2x?@U6%j~ZQ2)E*B)8bH+@mll3-YoQcC8#obEMGho(%`i@ z*JgfD&uT=n4Hq(&8(LD~UJ$A?Ng@mm1rdayNhxx4y97BcZ1M!G56Ws}B<-kvtqn#L zAFQQdENTV1iEVs|fZJU$(0kHFE9M7*gE3H&)^mF3Q-BIv?+*Cry5T9|QQbV&JSYo@ zXwablhF^baj5p|TaJJ3G#G0<4V*8U_1O$(^%PtfENu>Wdca`fJ)Sg^JlTw3&UKPlk zNASCL!BL1ewS@vUplvlh@f7KGo4AmQG#E*Uhw`>X;4*eYpy*FtdWY5|Lh6xbKG-tN zDz=&=SIALemRYWHlQIHXA-_a7M}a8|WwAUPq8Zi-7S%3SnQi@mlQ>cn8W3#Crv8dB z3DSSE?BZ8NDL8}~DpXud3VzxenVMMi6oHqC+$Hw1EdeKTyGwE2M$E!bU=owEWkga_bNe)@g-=I3xjfGr-nh$XYsC&Ql~Df-|en24g-Ngp`2R z3@D>4sRJ9;$doiU@S$a;#c?Ion2#p-9{DNN?6}b$gjxdPpv9Hw(DT_bOZMt#?gE>o zrZr=pA%u3IDm(%|CY~gXI`pcEi;&>F7wuOxFwP02F&uSZgc}W2=a8$M6xq&fP9MNn z4%=b88+0aWfrNUMBEF%U8S!aKRK!)8paw|0z@IyTjKpt&_^2iNn z?N4x2L>vLtw9E&1h|bh7VWk*{O1lziD-lNsz^XwgeZuK7S@j1vwdzEXWXd)jGzJwb z8&rWVNvvjj5Ccu#x8$$4Q@}3XRHjjeg~T{1sgK~AdjC+Fxftj?S=1!M58#Z*Ga!)z zzz~?lA7s*ydXBtQP$C#Y7Z=0D`fUxf8$evl5(VBz#QC7uUgnz*LBDe0tH69yL=OX^ zAUl~P32V1RohzsqSWS!arL{F8(fRmmsU+X-BBUMA8iHx_S)5*t004%SWr?rN&zwgx zogceb$Jv+&)3PjqdQ>-!ofBToklo9w#PQRKKe|$gQtAg}K_g_rX7EOGgk+#74d{rV zEv5}gDr)v3D@0KE>E2hUS0`(}3gtzl*)$Zgz)HKx19HVastO53iRw6_Y_wx_yowl` zJ7zrciZ&I5d<=WsELy99aZ)@|M;qU8Nd?2tu~>ac1342RN04+?UY*)lUMp5p`@tS1 zG;FQq3en0&#c6Xll@THFz_bYrMO{2?R=8xEN`p>-v{g2UVRtDYTOQ4UQ}A4gD+&OT zuCy|vh~o04e(ZOiiVhSN>*UorR8<`ZrHF{V09)1$sWK-T;}*8>E`HQZ?aLSS+CWLn7vQ zxn&s^yXppH+<^cU!mM{v4J2Zn4RnOYD0Lu0%d*NQRu^lloW`b?Ktg@3UobF7G?qXD z3m9bM(X_l-0d@BdVD48`8f>M?7N||8cx;lL8Vku;lAyNjC=4Q1;8K3l1G~bbCT&vy zY_d0yKvJ=15}gpgG92}ufZ!>0JPIiz%F_zG=p|z`o`x|UYDo1&XiAr-cSy8jOB{(f zku|KZ?sDmfUb3B6^gPoHkwD~bdV}d}>=dcmv4>>*Jvt*odq{!@_5wNcR#6CTBL)PL zEf+e9X0uMAD03+SsMKM|Zc(v>3q;ufG(Lpea5T4rk*s!iv#y8}C(|!m&#>9<93Iq* zXt*)D$45e_G&~{CST1abtCA5J1x2J0GPxlKP`<*H+(~myxP9bXfq&LGPDF@cTFWGx zVub{|FWdrQ4R9U?EIqFaA$(Ft z3-i=U@!782qIjo5mc0Q(!YT~na$@$G+c6SVnX*>f z2qn0Wgw?S2rqPECEwk!pk4wcIS4L1)_9%PYdr_fe%N6aFov?;VC<|16ERR9OQ72DJQ4B-3Xc+AyEv!(zFCI+cbes5)&# zgtef>%c_DafTK~8Stz4ks#B)%Ah57^DyhD)|M!a0W`W{4VBK>d+F_at36xl?kRIZH zDkj$j68Z#WAsSraJ=?iS2l&)triuts>ngW!DsB#{Fn})$1WgE*@;DCqjnuJ5zB25p zKdJBt#lndy33aYSbQO6UPz(fFKx&0^|Rx9jj2Ry_%qQjmO!#qc!}mc(IL zA+X>X&)|8n5UDj3Nof2Bn?%ob69Cl6LqXV4%_1u!mC~e5=zyx*s@BSA0(XXJCd&bP zE0RI5WnWMcfN6pw;K{rvwigz?>ctNs?VTWG-Sc!YbVoWuNXw zQmzzb)Gxm}zGM-`K*|9sOWY#7N{GKtrtqb;kbRS%T+lh{&e41k#lsW|acsQ@=1DR$ zQ3}Mta-5Q?B2f(up~c}4|dt{^di zIMwo?MR5j{*sOM@fVfpKv1Un1wcK7qUF-vx`fq$B-mv?YlPP(vs2mFRIdZD97v>Jr8Y)jarv#B4}a!r z^DwOLLWWPRD|wLZ4VN|Ad$U{=AigX`_h0fD$&!#=WUh?c7CAw&=;*&vOPKIRF2li^G z_6UO(7GdkC4eW}fWA?g1nB;Hjk#k`@ic4l9%r!tTm)GyJP>!Ymjp37DaMW+u3*!!M zwgkV$D(jxs0biDnzoh~=Xj|YVCB!C}NeA!uGs#*5Ipm%sG(mxf-put26WIjU5EIXU zhJea|Cq<}5%-}uoP@4*kW>SnAy4tAf$I0|LHC8Sy=pH1?u^<-0U+|UrkRBxiVg0^? zY^*tG*1-p|K;&82fGcC0L^%w~QE?iHw846kuZ(NAV2$(BuZxW96BR$Y*1ACGXEhHK zFr6|Zyx7k^K1@v9KfYXFi3h zltR0e-t024VnSgKfsu3sP`e2y&RmC}n*GPZy>XOQB}vHC3hk^8Gw^wms-nq+-2wpc zcVH&M4q%X+>+5zEnGmHStPo&EJpGvNcP@hLFFzvvv2?B+S;N|yo5ghL5v$WS(_a+{;MGb>w^7*Z+&p~+}3 zZkit=0yxvrlRPUjtAZqSf+(tBYpAANoyX%UTZk-45KqYE7naLcJ}6c1ii9MF;-hivwx+DLsiR2X|9!&Ft&8>Oy%!cdv z86T}F1}5J~0HdWLQEHl3fW*Lc2soo4aRzPA2}FX4!8%T00pcJ$NdN?+XE!7ja=}FS zT=c;_*MqcrC1TT2K(q$642~%gl@MN@B1Dp%1~>$g-(g$vRA$eO=ttmb4f|#lu0fTm zROOF79X)!l$f&HdCP7jI=0ahYA|QbbPApqb3LWGg)##G_&qE_6CNc6|8!BPYDHbeB z<5Sw1pMpqxw+Z;m$|3d|?bsMV6ZM7`h>bw2H8Dgtc4-}?0U)qu_!Uo}$DEc$1x=mR zRUul%1AAadQ?Q+rSuFq97)N5bA0-4y2r2!jp@MCHCX9I)O=g2RR@)C6OF*y|TIn?@ z($EwISo|@}wj8{;9O0m_%Ce9Mmi;gy13ZR@>MoFoG*FO5fL>!-s7XY!rExkeh`b^s zHZZI`a~d_jp&#vTZAh%_d@m=p$c0E0g-whavm%wyfFhgaw4~ZrTQ)TA5*tI26Abjk#A{ED=Xq5h;?Fu!gG2|-LxZVvannYlO{agM!c@lS!B^1Fr%M; zZ1(P{GZL6rV3R9>6n@(T4X3JUM&pf?StQHn__`}nu2ZMGk$cMIOd?t|?bkM$1sx?+ z`CPRoEIB&vfM;l=WNQSw1^^HvJp2a>ZcQL!5?t)0UweQ{9;o-9 zq)eSvNPwc(a3bHOLrS-LfgTB*7o!!Cq3t4_pavskz*!X-hhGp?Nz7iy2b)&XO8Z|< z$Ogs81leO8De-IaD4wx1nW~KyF3FaIObEt-G{hpt;mg5nj;t|h0*=J;nhHxX$b-eT zAx^|XiD+yb)9I}M0hCd_vos%OMQlFSECF@y<_-7*6G|B#w=3R&L8~b0trQ!Zh-|p0 z0+8Q{d&rsKsBkHpud?H%nPh9k6b)a7Ven83dQyHNMmA76KtP?2rQ|A6s3_L?M+aR0*ElPAu!g(K3)wdh-w@^;#Ul(UaZXPWGJfYL!RQy zO$)l_0p}IE%W4PdxqEzA9DH-*mh%;x-CcM`cGgi*|Ag*bInT zjj+euBHP?18mZ^X?53oO1Q!ryJflc@?IzC}B3sk6ZKjss03Bp$sq$u+-_;d&RtDI3 zeiet2=zVnDt9m4pmrI;+`d*fG-X+BI#6l&IK-2K~mHWg@1_gx&1cku>p<-%DA<{5SSyTKlx%`y z>qp!T-t#vV61e!#qj$`r9SRFbO3^4y?VC*G*kwa>TrZ7Ly7P75<`x)}IECZ#GvwL@ zwYM&^^XMA0)vMLz1)4-gjF3}~#FHwg=3UkkQz)h8MTB^X98Z*?o)tm3g>$yf<0L(S zLVHkx{fM_=kiu*FjqJsn;6d$gCBP+`>SDVkl@gfD;4`qD1h za!C}#fcGg<*}?9N(g2tyu(Cu^VicN2FgjW$+gqMO;NZ+QNwUx5D<`!LP!=G`eMh9 zUJ2Dbop-Tg?|MqB+KJJ{NH8g79^U;_te4{Q0liI%Y^DO1Ln+~o>Lio!v;&909$p33 znh{rt6|zBN0I-2cu8=pZ{AoxJ6kBKUoVwqPI-9BZa~@zKGw!z`jv|+yz>N@lCDV{Y zs5eGXg)y28(@5(kqYx*Tk&iz;)z!nkQS!>r&)fStD1*Ncb?2JyKg|hU&1B zmtcfIgE(Ugi_j{LM;uV43QH*RYaFK5s_tRvAb7A<`{oFBPwIoE@@7-R5J5KOfG>Fw z(fUPuvI&P%b6CPAaIAQHAQW_~wkqqG2`hDST_0-kW^DikG`fN&cC2Fps%#hq9N=*} z9c2zw1xfAI+qhd4{0HG-R%XSH+|}$4rr`j*W!DNRk~)J7Kv7bl+f-nz>(gFSDtvcW zRKP%vDh#m`oBnTEHPxWjn?D<%9vLPdHiVIJJVUGOQ&1674$8h7LphzNKt(1I>eUrW zN^_eY<_9=SJ$4(y z^K1-k@F>i(untJP(^%ZbdCN2UgJVC)ZOlGbWH(HJnzkiAH+6M~@Vga5r#&7H{xODw zieR|k`zP_{9AMM^goODBHU%>wvZ@t3d;gYZoCdio^HCrKU5~av)G*c(hfIV*9&Zuvj_SA(Y1tBQV?3+wZ($R#`` zHULz&0dcOU$-Mz^c&Stxc_3iO4oZw5E3w|t=oL_-9repgISb^iU_8##HQCt72MVKC zOK~p^>FSElqhyYt;AgVyiC97D6D#LZZs6BBVPeNsiBpO!5t2i`m71iPaY&O5^fYG7 z&+)K@^KuOttO`7lfRqK4oibAt@hG>(pRklCY?5yGB5wax4+29bilsViY?k;)DtAHW zD2&P%7`vUd^9*Y3A5`oMMpywzKy8(sCSLeReG$VzB<~wed6bb5&Is`mB0>`iPgfj* z+Vy56U}$f0xG8@?$0UL*(BKpzRZ+s))xk5Z9TkzFDswZ=Zgx<6I$sn(>e7M?QL2Yj zCTmXRkS#z4rQPErg9H+joWL(LD@ulfHsy*Od4>yzCBVB~8rrb|^VYyo`6@G4C}`CJy176Z^&D%6yVygiEuzJF)-??f z$stM~JJ)!`0h>n%w8|9%oSB`M&f3GFnMXSJTsOql(-K{~gtV=WY#Tx$Y>HUQ;|NK~ zJcwr5jW|3tlds7AF=+E#63&0RxtyS1?N12fdr(!y&jHYQG^pmAjVQu20>os22?C_7 zKtvXMNmXxNGN)8TsT;?Ls=2@XOR*`Ovy*&5+gw=fDLI`$zX0X9f-M@DC3mi7z$xY3 zZDd(oa?4nQE{RmtUq>U@QimilMtHXe+ZQPt5P!g_X@VOI#+F$lH7%OHz`*597@JL? z*TxLtUg;vj-k9neZB7U@DzFS!W2~H~17|%18!OuaAxgIdHANFaTTn>i-@rTFYxv=3 z!6zv(T4dApLqGjWXBd6yxq3BfzDsN<#^aovs0Y0bA$)?{Z ze1pflJmbm3+W}jUk)9#eKf6&2shuvDua&WojC|*ai4B6K(_b;cc*n ziI!=s#a^;Ombj>`KxPbTB?wm@8(B5Sbg~tgP&fR>)+oTTd0Z9fd_b&z>^78x3lwDR zINF%Tt^p|{0kt(a%Bdm*SP*oTyNe#&`9nNdRC~j&n3Sh<>peVLmZ%wmb#=3z+6g&9 zJJzV@1VLxv^j+S@)ffp94pm}pdy`9Ei$BW)Ht#BWX(bYdVT*w%*AW?1=TuS+t2L%s z-fczP)%EDri6T_9a2Efe*P zR!t9iE59!UA=V2FOoSrz6Jd2k`i_|a!-4zDq48_K=(3~6VEmV^ zBrDXAfpWD1STiRm1NU00j@s$qQjN}P=!=yW)3W)MqlrWi2CeQ{#7c*F5MkAx)b*C#gT zXk{~$x=2YR;-w+~sR||8S0jhUOIiRm=FU_H#spr)^!6=xDSAvg_=z!%%9mlK+(k2~ ztdGioRR;nXVuS_VZB=^(8jc;j92i(TJw9_-gd>ff2oS-yO)2NdPD_b}z(MopE(9ry zMWSg&4T=+Y9z>T5iD3!s%0?#DAy{=jE7wJ-y37<2vkG}Yi_%<^Ui-`+Q*VVSx?>HM zoRuTH)S?ccR$Z>wuCdF{0nP9P-fn3gTo|ypaes@v^8N=R15_hAI-pQ)h@vDJ;W>rRNr@ zgu-Qyn+fK_q$E`W0HGmgYXUM7W_@1M5Wj$^bV`DP)MV$EnM`Tf@1+vQmUJf$_ z%X1tP6{WRg%@?AVVrJFrZzT!mJ3d7B-bl>++wPfOtc5xm$==u031z_Wp=uJO$|tuB zB1POfd7a9o`MA6_2N$jm3!iwRUvlX6ChCVATozp>XEp){NF9#c!9b|7+FA&NaxSRe z70@*xHl#i&#q>C17JF95PUtIn&Y>t=qUy1UrqCp$cAbF8PQN+qau*Hrgv*`O%p_r1?{~@?QxILD^G$7x9;m`^}Im&#qvKkxm0?G-BiVl0NN zK_Jd{e>#J!gje3CM`?l@pq+6=RqjA_0cvcgqLl58kcqJC&}6-=e6Lfnw(EFoA2q}m z$WYy|C2nrEO1ctriRbM=#x7(U0jqIoaYGOa3J}E!RS~K#k5cw)q2(24WB*iuhm*s7ZII#LQvInzHpggb$}QHIPn?{iNY)T2Rxm10-t`Gj7e zo8?9~&7Fyngi_na-Xy-sb|R^0)QInD=9oncu zF+gVh8$@lUr}tWG&kzPdgXIk0*0%ax~vReGvnY=|3)3M(U}*7pbl6=&YdxVRlp{n9w+n| z4X-F|%_8j7`P5q0k|15xBdmbIV&>WWI5U=0!H$^3htU?JQ5WKH$UwyD40*Q+UN9-O>67sc$)~I(N2dM_C3bI zJsz0g#l|}ZCG}ve72|5GT#+kw2x-9{NI>N`)xN<^ZHAMQSJP(c$ zf2=7txs;rjGRYnYG&S#3*@Y7+=Ie%G3Ks(n;uvludC2!LLkk%1Q@ zPDLb`Or*<8Qp_k$eNlJe9T6!MF<_5H9H$CJ=B4R)Zj$a;4#FCQ*%A6v#Q9VTA?1+` z7$RIyt%mCN(jGgsQgv@VjZa3^d1|PKcx8}AQxz3a=QCWDuO)o1^X(LgPi7VvOQ)pHL6{ z!Ji9<2kQ?zEdsI-_3CA^;(}!;X|V5K%9i}IW2Oc@&sjT6eFydy0}NYJ2DmN_5K2JdGzxe*kvM6n1(+ zDB!XTu?cV(bLX;&V$GR^*?UeRZIOBPP;-xz^N15v5yPXh3=z>{WKVM}gt7$vysa~W zj-$vV1gP4y%_%`U4~So!WhZI2s}6Lp5bSfCw!dl=2}ZRDfhk6?X@S2TAD|@^*~RSj z$<+!-yTEP`ek1}2y$ni|j#)G6BOiOmdd^m@qXoN+iTMuy6=123d9&t^Zban#H-!zezz091qw+^Oxk%`ABNC~yF~er` zqTVph#>0VjjJp+6_#GX$?Igo#JgXm|4Z8qdPO^CiH5&(chNPuG!MtSOqM$WOhLaA!E_ z4bFj__io(KYjW5{LY$AX~>ZmI4K zwMB$64Q95Y$2otb!pZ7%9R^(>@US3wjdENzJL>_P?n>cHYdBM=q) z4uR=Zo>m5x80h$;(o<3#4i->6i3o!fGYE9TJ_pvhExV^Bw?5L8IaW2e)ttABcTnt3=vrf z6kkCTcaf?mH=)33V2LCEi1EpLD@2u|(9{hq<41Y${ESmWhzi7~YNX~3WBEI4C0|V~ z*eXbpxL#nPO{&hH!Pur0p4~JPv?ALSAlRYmEr zxe0}m93{=jx`dp7!~5HUsgvhgRk4X(uE0gPP`sja zeTBFZc$?t(ak{PKcfgifsu8X1Y(C)ivQ=~BT=jn*!}+*a$vLl*R5-!2Cpfwo$I1Co zL zQS{*GHro4JmFPd&iW&(`vRxJzp$-X&jAJ$~&fjAgEaE?^+961VwIN=qrnR+xJfAwu zY{ZAM&QnOedRZh=NIzDK?w2>1G;4DRC*XJLP7#sjhmE(4{QDy;qfE7K!R|%EL@OdF zO4O>U5vs)NYPI=5eAbvJ;U>T};Y!ukvki#H zHAo}}(ehQw6TnuOxHuWM2$5){WFdVrmO)l9C|AzcD`H~H!v ziFP0}xd~ebQWxN%#37|QlCWkLQZg=Mz6rNz*9fcTvKK-5LhF$?oWzOL3(?gk9KlxK znR13uC@VFpLxRw88F}xNg1lBgsG{SBiIH1=zn}`Arq2JXmx~t zJ*H2Ht}LP+fW|$y6z1S7@jp zz>XRMH!46ad7DP|p4Vv>Z9YI#Vhv4lQKQFhR5z zquL|OiU1vCSwwerBq%X*-ce`)-iYQ@fc6(a{yIaf%TWY!{L5>b;`?w9*R&Gq&5^I}obK~)@7IB%?Qgs75NUJ*ry z01iy(%YI)$%@iV1gPE2OJQB>*m8EiE0I4LBK$l`T8$$_*D1=A4I6c?YRHdp{708cX zi2{1nkO~jtaHcYCm-MF&4pxH|zVv<5LM;#IDPB<|;_`!m)Uei9(FuzvJCkFp0hL|B z%o{tbXS(@XD_$Mr)#d6b;?5+ItFsv=a5TjiPeg0A)irtzQfeqzfqDo8{h)9o zdtR)zp}VjU4fbgx?f~O{h2vSC*DQ1{lJlaK4vmWeKPr)Yrxg@IwU_$iv0<}SD9afe z=-FFbkh$gf^PwuT`pdqeD&SLvLIqE?0gwaT>N%nHm_A1v_M@;sdnGIi*sDx5zQQEJ zC^-(K$oh2~X_?gZ;>`XnB`FOu#6-}u=xYs{SJZE|;iiC{&@E9V@>eSSflXso6qM*` z2H^o}U<&3{9G>AUxq!4eze1^;(#fP(T^Uz4oyBx>4H7FLJqb7;fh$dQjwLj0)PWmS^ee46%7TwHAhQMLekXUIyY>g z5vXOQ-*znZ^~E_Wz!HAZ=1F+ZUU6D8uNX2mG^!qjNbzUMStdHJD``foa22SlZ9vXh zArH=kB>sX@E(;qiwJ~-&jnV{>$hukP5vV{jG&Ck~gJ4)3&q!NGh`ej*Jj%^@L6LDl zn8Up>S+wRUz9dlyUdT9zth7jgbcVC81Ob9=W4<^+TzL5mXu|8syaJl?!^mW?XP;PS?UHvC36W zdi5gFzJzJGp^8x(v*I62f?cg+R#QtJ0oTjTIB-RKwWsMNYjVd2IZiWr-xNZCkajib zKNU*BU^R>w>bS`xW}}Ca1S6WS8Z);y2k7-tw%pztyD3x25b@aD?W{!1&8B9CX+g${ zIA$1Bh6Kt~u;**NE2!i%Zb@d0{j^GL4TGH}<=pd@X4%#bF zlPV~1Hg)aQ26go=s##4s0r`;(6gCEog1I`Dunk*GNs6RebM!SqUww5xCU9)Rsn`?8mJo=`wNW=kYlFocI3RcS(D>no?$nV zPJY^5{t>+hCd4SS_`bnd`$j=UYc9iPcxS|<`j9awB^&~mt~Z$JHzFi8_6cy1-!Drt zRv0a55}rmnnzgptyp6@gT(n4ir&=&20JBW!NDJ7f&hIXTz3D^_HO2IWi$SnPbW{+E z+Nm;WuwMC*(0)0mGE5NH<%x+HRAI2naKMma86P87O}u(y!0bLx7@G-1Jl{lYEtGf& zi~8ub5;cO(Trd4Hh}lF>o^s%2RgKw`WLYvpo447_4tN5QyL=?yN^H8wLM5XOY!Rh^ zVmeaLYkJ#M+c7EF0*)m;4%novR}OtN?FZHRvy=yx-Pdpduh(HUTFVDnNm}~F6;y9e zG(7);2;xW>iLh`$Xfk*S1U4-0DwepmlAx+=`LevH3#VPU8ZleF4X`hW75%Hpcu?MT z7Ge+5`izj!n{Wz9aMUsqV$7;}3;M!fpX5&or-SM7YPzAkraZAtVB%^^*9cs zG<&bi^%;|}7zJO+6E6$}WjQjrQX;N$bQM!Yt1r;Aew{_OTmUUda%B`t!GCXvK`ZRp z8fXckKcN8VgHBqIS>5Xal}AYhJTOQ20Ous0L^1@*p=Gdv z0dIxD0%RR)Cv~N4Pu6qUE?Zwonln!MU}hNIUX(UzOwWK^VqD649FW z4k}}>=#n-y13$$C-2n2u&4 zrnS8={Z0$%TwZe-tzROJ4etHK~tFS1t}DiW#r@#q@++XIm&Iip-i*b+19#_m^1f?1gq^tJw9NZ@ z05Dod=W9bk20R138?40ts5l2AbDUakn3PJ;;)OvFuWV(O1W8%?sx}sU#7BU`wz^Q?l8436lvol3~Vx8d|-#bp;!ef}hj? zLVH9CnG9#39)yt^L`|3v9GC+-l(TRrp74;+Q>VchIvrMQCSd2RTUl{Z-(zLOgNOYY z1IT~EyE!I$?8sNEsB-k;QLP;_ay|m^#(JdLboSFtI&(n-yvtA5=L1rSZ3x&{$FIAWDCK942zpLv;7`&P=VkQHc zE~rbX6>jhx@+2?L4_b<`$LL$>u&?X;@e=da@gYkv>={rDFw(6j)9jqqrWBoQL`5OAISu%djKN{KAccpvk=_?aa(q z=`Zp)$Vo7ad$>oC5Fz1;=yMA|Lh| z=`_22#seXzGASu-tBrPaWDGPyD@mE>Xwmw0D4rnZweD4oo1opxv;1s)g;w14TW!H{;9AUZM!-0=mtqXT!dew{zx)l2=x6% z0|M;FjJnv{OL&4Fv6fg2!+J^!yfm^1M3F(*1E(o$Kc!y1HSpNxH?EB8Q9l`wCoHCf zA)GcO%K9cZp#5%%gzBLLtLZRs0re#Pbuw2Q-zJLD8EN2V=KT~e!s*BGWTa& zF4WSfLr}|z(mm@jZ-694EpKgC&o)g|>R4qK*f2m2FK3ewbeoElFnobY0|S1;R=Lx3 z4vK=D-0<#Nd6kh*@+6IqEkQ-R`GsCvZADgKwCf`!H;mAh{~XHCU}T+Qu- zFbe=*>JG*;ApqOL4WtF%^T?=+n~2Arjq%h|x-ZGPG0}$Nnw$DY(~S8u#pJA_3)@)( zMo;j;sbM9kg*%KlqC&~oY5tt|5O?Cph9S#ft`cqrFIS2V035RJN@!ee;sEp%oX6Ae z0YZ(!NeGLhW?>HaG0*1i>X_d9Sl+3bLa9%6Ds^3dp(uUlfVP{Q0!0B3H^J|`ww9lC zf*L@@JF_9G{n-j69f2axJ)O=XD46XHWWSM7VU>p7Lee0A?v;TulQ6W1U?3Rq8VdCC z-TMj$D6<4!iQ00bf`aaYybUMTz{nSl=$LrWnIRFigBRxa45*=Cy?(;r{R*7W!~(un zG{9<0u$`@^n8-)m1tSRWO$fS5RsE#AO+kQ(Y$ zf&hjsO1Z>Tb~6wdK&Rl>%gzBdr8!r8Lo-ginVNj zK@&68KVK-sSR^a+qDiNk_!}C6ZTfby@brIVx?Y9c|Mzlj-p|TwX0v{Zj8o{Uy+OD&{tKq_k6b zOsu2#cu!_L38isq!j-UhQ(UCtF`Tm_Ya4eZwDn2}(TGyoCMn{{HixjVtL-3cuW)}4hxELTR zK!f}Q$MXVS?^dDAQa)rm2tk7ZvLsE!ve8Q~CQ<-3E~2qsd6JKy+aL@BC`jm(Vy;{f zh?P=r4hWqnCr9Uuac-C!1l(IW+ZRJ!{|;ezs89enO>2x&T`4DhRG!_%(vs4_fLnQ7 zk`qsBmEtKu)gr2F8LlgW@~Bf7QIwxE9{%8~%z(gU_0vKMUVETYu#KSQJEfwR9?eC3 z=FW5!;RZ?)@A|1`4q|j5q2*l_H{xnnr^Aj#H6h3quB--ax`wUGXcVpjZz(pufmam$HMlIi}3emCTgy_ za6z>XoSE1PJjTj!EB>LA6sJ%#*zkl{8b$aacss1DDJ1fw3_QI*3AK@iXwv)t146Wpi?1gfLf)xBGSyM zm15!|#KK1(6RxR_aH`30DZK=faM&V=V!?&6p2OU*VKp&GL2L`*q(&a48mbQ5qC}bs zBN=#;>-=a=R=)NwO+o@&U2}eP69P-JSm9j*EKuFcyu^*lPbvUlS0aG0T`QC%(qGx6 zY4ITSLGZyH?V~8z#gi?gxe+@RDett)mej6m6=Xo^F@uKaK!qWz=Z=X7tAA8 z4SgT{Wn8!GrjHcZrn$}=E#vI}vPnuYiLL^1KP zQDU@CU6L&CteFW%&CUpj-9##Eo2S*lcJkV%CNRx*z}=_Ry>7w5)IEInI;n&}P*g+8 z5gI}&FL4zD#3Tu+x+Urj9iXe0P^rsQagGBZGr3IP$A6%{lM0~OlagifCf{;XkI$mMyy8#D$T~v zjwIgsCiq2Lv7%!E&rBq8s;~1e$rDg%?Zp63>Lktz zYfKG`X%oai7KB*lYaZ5)IXjL75oHc-B26Y^Cg_WAP)4s&peKDYilZ3dt};AJ8lroY zrn)4EA81}vH40C4M!+CB8|Oo{;)1xS@JVZ|!u!$~A>iX6CfZBoFsq%J;>49rJ7{CB z6~=A7#3*mBtZs^mR?J30(&VRlQR*P5y$ulD3Mflv2cGV%fF>rOC;afx|GR>H#Zy8> zVnmYCaFUi$Q_#x^5)*MDJO%$ZLoNAH}dDK*G_Y6I#lQr9nYONX!x#z@U3M z&LmxbS(C@T$Sh|G;!JLXI62^zq&nFWjaiixRmD_5uA90;k_6M>v{|;=o>f-YaTF?& zkhQb3%C1Oe^K{K*0<62rGF+lNzOo@(GRv0RLuS|==u%ALdyn^Z*eBmv?Pdgk2N6ID zrKxx34{<>>)~Q#;1=(+ZMnZdKEW=!7Z&D(%TwfR9WS=7*xF7`Gm?^A%p+!tvPr;qy z)0hIth<|@)EFh9{p^ucc?p^%H>;l+vYSvkrG&M7h4Y`4)W&7==)Hf*=6`{$PxI8;{{#{)3#ojcCQ;n7X)EApR3q} z*oJ@~$s&Uk$y|X0BUwUNG7b<|&-2y@3FPkw?A@I+=X6(BRrjnTTBff?ry#s!!xU6Y z8x*`m;y&=He}`C18e_sDju29YKn5^bMv>D%hm8!fIyMilircGkV6zuyLqL>wHU>=Q z_?$=pg^l^4#Y!WMQdm7Yas||=3lQRkoq=Dr6~RQw!3VXa6E3Rl5!HUk^-DLN=}fAG zzQjc$N9wVdSiwx5v#7)hf-KZ1VTOthWtrV8>dBGh&bQ6jDH6;lxiaEJ8n{m4y@vg~ z!cFDl9k8htqlnAu*)lkFw44z25L+wwyJ4XwVm-FJQN<#Otp`hM_(6bFg<~l8OsL9& z2-wfH?u!YQMEX6NY>a~>oWX9@o;!g_y-NnMFI})zlvJFd9CuM$Ay?W-sLEO(gjfBj zhM8g#k%i)0D|TUoTMAQ4E1Le4skk*XbLbRaB2K9^TxyV?@yjUsw8D}so3dW02 z1AcvrF9%&^r4Aqk!S25Ppc=y^ic2k`J7?~=%$hvO;k# z!66d}BJ_D5{?$@#L`2lul`7;Ycd=(TW?pa(Cc}dcOxjXl8%8;TM@$=;Qp@J38IGQo zz)HGl02bHtL$2_qgvLPCf6uO3)5kKs;KzG#flgGiQ8m6G(j7bwWHvAfkXe0ZGl8!V zNqBxvMRq#N$1}}-;6SlSi%W%Aafnx6M-ilSTWDa$d#QWCmuFBCaWI50t0H9BVW5-w zcpIePq0!u)OiOQ6M>BzFa8-SF5D7XT6iH7o6*gecoj|r_{R&ZaU8qleLpjbI1`2PwBme|kA}pW{aoV8d<&f-|m&o9=kjdV zs2;~vcos^=ES}S}Y1*WE+_k0>jIm#&u4L*4)m1bLqwNfo9HzRdtnjx0aZqUA3Wx_< zxe>x34(g|-7EBUZm1^gr5w#_FnoFa}8Bt-0?V4!MJ@9bi!x9++Rj#VUOZl2*?SMFgj64J|5Yc{9{3+jl#dc3 z+Gd&~0ZAjO@M{jrA@XEiY3Q1?IwTGP)%xE?XqgNlOcsP7FObW&R$r>hJV=s+A!r6k zZ&(*0jM89NQLr7>>NctKDs1E>2)2)BDEwdN%y#CWhK~ZOM9^;SgeZ8Kdm?2PY?7%) zqWjuKS}v#!C)pj!gAoLkm9mm_)^!6q|>&}HZ*dvB|f zJ$q(B@>Ur!PsLl%6u)HT{c~P52jxCY)%T$!>F2RUfJmTDgqVS?#|Ou@LYXBPYpgoK z)x?6@AgQQPf_L&*9Nk2uZsi^klE4DA{K+8#mR`=GS!tToGlPf$C1&rTqHY8Vp~2B{ z5F409!Mp827Q**TvyV15cO`DDG(A$yhp>h)*(nse*xDz0Eg$Yi5@6RY@f83&m}B`g zqIN_1r9M7Zc?pq9Lx6J{*ieCImw_Bv(G9hNMX;8u#SJFHqvP5cVrj!N4O7!>oQ6T% zxV!?eohztDtitNVbSiK}H&QQY5U5rasJ!vgeufY~V-y?$LXK>!cFFRR3b#U!$jI9= zqrNbzEAmaOLgEkdj_BapQg?7X4R}(Gm+6u0i3Iqpz=Bq`MuMBNtilAw3QpRzJ`0&f zff!sM9LMLH1ibU)_}x_c95tDCD>;Deq_H%6*~Vpv$HbA=L!6vn{n-Qr_VJ;44VeT- zFC!)AQQ#tp9@vo{nZYbD;~<#?lrR{N%8@guGD)c_l#z5!L*sonQ6>FnMk+W4(SSm; zeTtvSP~cWB4!I`VR5GKK>$VRp-H2cTN{Ofj-qG+gDxB!!cujm3WFI1 z=7V9>oHY8VF~CMFAJU;`O@IlC{mG#EXsA?PD~{M6ndA_&U>0cbWLW8zj)hIr!DJ_l zJD@2UNZEs;)Y%bmJK&U^$qF$W9&1;MU!+}@+BQ1uFKLbOv+6=EYl$})W7@oH?Y2;J zTmd5}*D47@+moUAmPW!Gq8k6Cvy%v7HZ6*fwh<|&X`re_7E6z-W9lHsz1!(9yz@r=a89* zQAr&%VqqSf4Be{07RJev-^|IYAlJQMRn2m%;AP!i&}@#i5#Ms28w$2evkttXoCts?r1!R z8MDH(C7c{Bvi|-yTerA**8$&Q*hkX^{J=pecWesoXDcw z5=C^S2oPnROO)ATBYDf#guh9a_{Es`3&!&N=|}a8GGvZ=F`0Q-=VN=V8%gCr2z_wV zCJUPtP_i8;7KMY2>*J-yB#K64B^9q?q1X5t(sD^Y!Ev!-90i`Y0hKG~4vb3BlbeYw z6RqGm04(E-66)UM1)ShCYK6l}))G#K<8Bqb6CMbTGb zSv$lRA}Tp%A>4-*8f|lwAu>rw)`Kb*ZknBL4TtfnyK(L5hh#Z()Wm&xBk*&@cvo@T zTMZHFaI-R_w%x0_gD7D+Bo%-p64vFxk`QLuthCCjEvWXqfHS>=IJ7{8z8Ojyl>ulz z60#7mz=|TIAonG-}(#ir6np8rGY&tB?YVoH1wq% zw*(Z2@jsdmBY7_5(dgaDdrVZWcq()P`hZ?769;G|(S0vQjFBq3r_%DlXOJe;f`bLk z4^&4qp+F3J5EYN1Z(M<0+YZ|A4{D*@@|sa2v*BP+!WCpW87m={9$ams;wF=7iN^+t zn(Hb<1o0yV2)ndxkE!YoDGbmmK6a+~&Z+>s-)zv%F{+q4M4xK-Ii-j>m1aRGX9(O2dRHT0>7F!JIgeJ=A_N<~%TbAtezPg8*6 z0@xii`i%RV;O@NkB~A#z%T==V_q<)|OQ#~t+vqHWus7U3z{*p@(q=J~ySWcbK&b^z zq9g%ia|Ts^BV+-py|ynqT_0gDvd@;vQxh}I}0CS-k@C-#%f>2 zHa(u;%7OewEj?t?@ltOAkAfLPksa!+CyeN%b}s{sWdtqd=1#)_wsHIR!$9K~+?)#J zSHKPy`!9PNk*kBv3|ND=>g3eV5KWwH^6b{&G~vj;x~$ky)p)DyO6VyHto0iPk3=hlv+n5 zOwIW)8mgv{5-;ZT#jQcEzSlOy9caO*XDgMYOG$wH<5E8-*iBAndR^w!o6LrEDB)Z3 zW3``X zM%XwbxgNY>2$S2OUP0EQrwBDoQ#eFjI2{S4tvb~Tx^lJ_s1?~PHQ5zM*+%(d;cBsS zsht3$g^-n1`9KX`&Q3JI+fgZEeGB~31R1DNCsRINbD41ETA zfGr}C&5SnUs86c68wh6oN^hNIU{!ZM7$>31)OWE)$`y{>>0Ib+zL7N&78%sb&;`t! z*l7$3nauc05y%=EM+KEbllR$~OmS@NW6}leWk-1ADO)0z43J1>9h4(lhjt)9y?%6K zXQP>lPl)OUrJo1o#^i_w_gpPMJOi((iG*oUnvs^rve^vhjDHhqlb{pgh#H+Lc>(r* zQkM_|u0(`Rg5IDJQwD5e-}5Hinowrnoj97!(Wy7LQStz@6rmusXm7S?e3)b5$JAM% zhWmCM)MDOz7$%A%6qU4VN8G9hE($KsYia+-=ytN6PVj3-phGNd3se+>*knE$nP!$1 zpZo@UM6NnkT7ZCKvJH(D;>&nM0XbNU3q3$*#1X2T*1svXb!c=6&rJUfMYUTTEE^5Z zkkw-*H)T4jZ(CMf3bE!Gg$Hzl8z)G#k-wN>3H;$6&aFzLL`dg0Xdl2!E141sRFn+& zu3L4c8lngS7t9CL<>9xw17Xl8dpR;__To0e?tVUPO|pc~ZN3)J-grnvk^Mq{b@n6R z*jp|(T~HIb4cw>X1ZpE{Gb3D(2+3d_8*3v|@`SgYH&5wDE<`Dqfi;^59m3hh`U(N^ zo8M)URD)1~9Z7-QXf~?DX-*7TWG)w3D-P>9B#=o<5x6*tQ#2NB*&M2=^N$>4G>fX! z*l99vrANI12qpsxo3oMl5Hm&)>P!0cDE-o=(2X^nce+u2Ekh36rGm7bq(YQ}gkq4l z$jFUpPEQ*umf7#rppk_TWWgk&J?3jFQS7DeL|J%T>94%EOJKVZ1Dx^_NLN0>Q)nbR zqA7x`99z+J#-Vv|snkKJ1)pnPMh+}mj zjB)KdV8D>bh3(sJ-+LJrR#2U^*VyVi6#7B2|kfc<^uyy~iuZNPQjOA(Z*lQo@0nYhW;G&Sxw+e_)J-`-W6!;Jj$CXJv_gNUXnHU3CN zy4|q)P7oUwlJpuF1%U$^O(B(yJ?sVJ@l0+5BBGU1>uY^fZPtG?M)pC?YmlG{x{kCJZ$RR@Rsh ztAy;i*!b1tQ_WfuMK=cVXNJP(B!o89$BRqD9K0p43QF**Ql!Q{$Qlo##(TCUE(*IR zkkw=l`(#r1i?IS|lvp?*qXB!9Y+=Z=#}kUpS@4)^P7SHJWk5`-j_{!YsP&0_;v;}O zZ(EDShXbPq)0r|6fUSSp}knA;NCdK&hq= z_=Xb_jPE&xC|Z>?#g>Q~QpYJt@SzwQ4GQR<)aUK6vV>u2Jl=@1W<Ny$=|~2hid$WH3Jpnv6}o7Jg_F(ne?q`|nvnEiqKnTZNiyY$TM+inG+T!ikJk zYhGPv2#5ggc{3>JU$V@0?;5a+gJn&oa#|5v&-t(nPE9Tq8F4XAik8$yif0e_FN;F; z5tvMMBvofD0G%Qd0$h@|%4$>A6y1A0PN2c0hnNU#3dOA{h@MH#VaRwBpTIkN;Inld zYCK*OR(KJYy1V8QA}h>Jjo*b_q1j@O6i`7tDs$EW&P0{B1sec%hs=FW#AT;BunqTW z=G1gmlz5irMunvYSJwsw7^A&JAmZj0BU+)7+_?`2sY1|EilMriZP;!DQEmZER5%<7 z&aubzLvS=vMZIoTVf4TAI!xu4FR_*s#V@ue1J;+rOautjQ`mSM@XFDSeiiJLKf&gMMt;i8Xt`A36`982BAu7a50wxW zRp5b9-m<_@QHIn!N1~S$;4YUfvQ5L9xci9cB@B?`{`Om=<|_RK7m!)+fmWKC+B;cY zEoadE>T#eQzhvfg159#IQCyjYcH3AA5GA5|QdF6Q7g4zFALs z5jZ|_^Swp6S!hQQb{ z!16LcdKv}=gK6Ca&c(sC=&Xndlzhp*GEk56W)Kcw^C~_gsXp#7D4%xPrGLZ=Knslf z`Lsv~g+-)ExheEA$a(N_R6s?Ee^Qoi)-Tx%PpAAzfkZWkM;gp*AnkIb(UY4Zo*^U* zF3&Y_78%+x1<*phkUOr*bV~eS6?a6L1`!zwi3lAakS;_WIpmIQTnHshqf7Owwx9T# zwkxcuGz3X^S_?ARgn93FW@VxWu!=gGufai4pe{`m1R(r`K5aFM&b*07Izc6(czFe1 zJF8KYIs_!8jT`FHFgAX)mgUia8?{-SyZ+uPQen5kN8Z&TOD!)cH595-FCYQPBoiX5 zoG}A1fQB0Y5)A;ed|k7~R8One$j45=6TZPMx6)oW9ajF7QDPjl(y36XLycR#M@=MU zcUlR|7)v|YIAk~>sWHQrwObOv;UU)n%ek#rTT%G*f7?jkxUYT#aRq0mVd zKq%nA1NiMeU67be|HP#Nubp$G7WIDC%i)qX{Of47t`ZG8cqBnAz-1?SC1@Zkr-Uav z?MedP>HU`rOw~}x}(6Ef(;hyM0S>2XD{37Hrfkh zuy#!{`&xw3w+r;IQ65{@h18MA1~MjI4Y!(iS*0!sz5zlbpjdnuX^-P0)QqE zSd^9k%Bb!T3PqQ9P!h5SMz(A=}kXkl@OmBZFc5nrPnd| z#n3Kke2<#KjXOC51%3pEMOP!XLT}&tSPwnoX%nY)~dRt)|imrrXQ0Ou?$f>~md1IpEcyUkM7q;n7phz+7yOSFb*O`F#8Vtsjn? literal 0 HcmV?d00001 diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index 0ed65003d..ff7bdeef0 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -169,7 +169,19 @@ protected function decodeXref(string $pdfData, int $startxref, array $xref = [], // initialize object number $obj_num = 0; // search for cross-reference entries or subsection - while (preg_match('/([0-9]+)[\x20]+([0-9]+)[\x20]*([nf]?)(\r\n|[\x20]*[\r\n])/', $pdfData, $matches, \PREG_OFFSET_CAPTURE, $offset) > 0) { + while (true) { + // Some files include comment lines between xref entries. + // Skip comments so parsing can continue through the full table. + while (isset($pdfData[$offset]) && '%' === $pdfData[$offset]) { + $offset += strcspn($pdfData, "\r\n", $offset); + $offset += strspn($pdfData, "\r\n", $offset); + $offset += strspn($pdfData, $this->config->getPdfWhitespaces(), $offset); + } + + if (preg_match('/([0-9]+)[\x20]+([0-9]+)[\x20]*([nf]?)(\r\n|[\x20]*[\r\n])/', $pdfData, $matches, \PREG_OFFSET_CAPTURE, $offset) <= 0) { + break; + } + if ($matches[0][1] != $offset) { // we are on another section break; diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 987a8da92..426cda1d6 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -184,6 +184,13 @@ public function testParseFileWithArrayXrefObjectReferenceInStream(): void self::assertCount(1, $document->getPages()); } + public function testParseFileWithCommentsInsideXrefTable(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest805-pdf.js.pdf'); + + self::assertCount(3, $document->getPages()); + } + /** * @group linux-only */ From 8942884b814e04d0301e9177baa6e3420d2c8f6a Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 13:41:55 -0300 Subject: [PATCH 34/47] fix: guard cyclic page tree traversal Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> (cherry picked from commit 1ae00811e55e8f1ffce9c0601264345545678428) --- samples/bugs/PullRequest806-pdf.js.pdf | Bin 0 -> 1098 bytes src/Smalot/PdfParser/Pages.php | 26 +++++++++++++++++- .../Integration/DocumentIssueFocusTest.php | 7 +++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 samples/bugs/PullRequest806-pdf.js.pdf diff --git a/samples/bugs/PullRequest806-pdf.js.pdf b/samples/bugs/PullRequest806-pdf.js.pdf new file mode 100644 index 0000000000000000000000000000000000000000..106de472c250ec1a77932a5f45e926942df49964 GIT binary patch literal 1098 zcmbtUO>e?5487-9_=4CDTfaY;5C<5&Y|{|*hIR-vuuiN&ZIIZ0{p^rJRge%`4oH6W z^NZ~lI+N$*!Fh}rbHE0<_+kM4K3M6`R)96)if`l^F+A3UuSEqe=1mb9445b~VlaZ* zRGn;yFL_qMJR~A`^!s5xjO4CR;F{=7WH}$oJ znpU>?Zq0TJrAz)&D3S_=&7jeudNB>(5Ox~G zt0>m$6T%)9tyC%aH`X4eS^#?k*M)SYBhQA|wjs@QbeD=sE%BmH&^0oJy&H{u63r%<^A>UFbbjikC_^7Kb70bjI%q`vV!V{7(P? literal 0 HcmV?d00001 diff --git a/src/Smalot/PdfParser/Pages.php b/src/Smalot/PdfParser/Pages.php index f95134b1b..fa2092291 100644 --- a/src/Smalot/PdfParser/Pages.php +++ b/src/Smalot/PdfParser/Pages.php @@ -63,6 +63,30 @@ public function getPages(bool $deep = false): array return $kidsElement->getContent(); } + $visited = []; + + return $this->collectPages($visited); + } + + /** + * @param array $visited + * + * @return array + */ + protected function collectPages(array &$visited): array + { + $nodeId = \function_exists('spl_object_id') + ? (string) \spl_object_id($this) + : \spl_object_hash($this); + if (isset($visited[$nodeId])) { + return []; + } + + $visited[$nodeId] = true; + + /** @var ElementArray $kidsElement */ + $kidsElement = $this->get('Kids'); + // Prepare to apply the Pages' object's fonts to each page if (false === \is_array($this->fonts)) { $this->setupFonts(); @@ -74,7 +98,7 @@ public function getPages(bool $deep = false): array foreach ($kids as $kid) { if ($kid instanceof self) { - $pages = array_merge($pages, $kid->getPages(true)); + $pages = array_merge($pages, $kid->collectPages($visited)); } elseif ($kid instanceof Page) { if ($fontsAvailable) { $kid->setFonts($this->fonts); diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 426cda1d6..37f0afbef 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -191,6 +191,13 @@ public function testParseFileWithCommentsInsideXrefTable(): void self::assertCount(3, $document->getPages()); } + public function testParseFileWithCyclicPagesTree(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest806-pdf.js.pdf'); + + self::assertCount(1, $document->getPages()); + } + /** * @group linux-only */ From cf28267ca4107d2bbf36e8561f54725d2c0c3632 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:33:19 -0300 Subject: [PATCH 35/47] fix: recover malformed xref table in issue9252 Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> (cherry picked from commit 35130403aec0850338d1a94103a1f092614f893e) (cherry picked from commit df71b86de26c1a3e4095b45f94a77ea79a58953d) --- samples/bugs/PullRequest807-pdf.js.pdf | Bin 0 -> 1200 bytes src/Smalot/PdfParser/Parser.php | 1 + .../PdfParser/RawData/RawDataParser.php | 40 +++++++++++++++--- .../Integration/DocumentIssueFocusTest.php | 7 +++ 4 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 samples/bugs/PullRequest807-pdf.js.pdf diff --git a/samples/bugs/PullRequest807-pdf.js.pdf b/samples/bugs/PullRequest807-pdf.js.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c9a5e039d641c7fddab1d62a80af68f769276c66 GIT binary patch literal 1200 zcmZux+m6~W5PkPo_+_Q;L+e`{6A7)9<)THs>?)x40quhq47dt5N=!xj^&Mw{lB7{2 z$46&oj?YYd_cES-WSy*UW7ofKe~YF4Lj+vr``ob=Et|toHU-7A@WV{;n-97depUv988`} z`O5^m(uhpl%CD{4V)Dbf+|~91+?0y8w1qWxT~tBp&vsqoWeU6kzurVfq#qgWt_%n{ z`(2pYAFCA@J{*!pVO$xGM=UTH1TXn&)>c3I6JAn)Q^v8%_-nM)AN~UuK181>)T;by zZUSBs=mRDTa{>ouduaG5hJzs>1=Opa`iNZAPi+}Y1xfPxXf}H?r?CO!3}pCX+&1hm zqcZBO1GIjR6r*{#~&U z>f-FioKR_7nyR^B=Jt<)IpByC-Ul2nAGl3sZsT#hIg0oB&{a59W`jhUDuM3qCePEq DD&#Ag literal 0 HcmV?d00001 diff --git a/src/Smalot/PdfParser/Parser.php b/src/Smalot/PdfParser/Parser.php index b051f1140..70dc6df7f 100644 --- a/src/Smalot/PdfParser/Parser.php +++ b/src/Smalot/PdfParser/Parser.php @@ -320,6 +320,7 @@ protected function parseHeaderElement(?string $type, $value, ?Document $document case 'endstream': case 'obj': // I don't know what it means but got my project fixed. + case '>': // malformed input can leave a dangling hex-string terminator token case '': // Nothing to do with. return null; diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index ff7bdeef0..7dce478aa 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -163,7 +163,11 @@ protected function decodeStream(string $pdfData, array $xref, array $sdic, strin */ protected function decodeXref(string $pdfData, int $startxref, array $xref = [], array $visitedOffsets = []): array { - $startxref += 4; // 4 is the length of the word 'xref' + // Some malformed files omit the literal `xref` keyword and start directly with + // subsection rows (`0 19 ...`). In that case, parse from the given offset. + if (strpos($pdfData, 'xref', $startxref) == $startxref) { + $startxref += 4; // 4 is the length of the word 'xref' + } // skip initial white space chars $offset = $startxref + strspn($pdfData, $this->config->getPdfWhitespaces(), $startxref); // initialize object number @@ -617,8 +621,8 @@ protected function getIndirectObject(string $pdfData, array $xref, string $objRe if (0 == preg_match($objHeaderPattern, substr($pdfData, $offset, 33), $headerMatches)) { // Some malformed files have slightly inaccurate xref offsets. // Try to recover by locating the expected object header nearby. - $searchStart = max(0, $offset - 64); - $searchLen = 192; + $searchStart = max(0, $offset - 128); + $searchLen = 256; if ( preg_match( $objHeaderPattern, @@ -1036,7 +1040,28 @@ protected function getXrefData(string $pdfData, int $offset = 0, array $xref = [ } if ($startxref > \strlen($pdfData)) { - throw new \Exception('Unable to find xref (PDF corrupted?)'); + // Some malformed files contain an invalid startxref value. + // Try to recover by finding the last xref subsection header before trailer. + $trailerPos = strrpos($pdfData, 'trailer'); + if (false !== $trailerPos) { + $searchStart = max(0, $trailerPos - 8192); + $searchChunk = substr($pdfData, $searchStart, $trailerPos - $searchStart); + if ( + preg_match_all( + '/(?:^|[\r\n])([0-9]+[\x20]+[0-9]+)[\x20]*[\r\n]/', + $searchChunk, + $subsectionMatches, + \PREG_OFFSET_CAPTURE + ) > 0 + ) { + $lastSubsection = $subsectionMatches[1][\count($subsectionMatches[1]) - 1][1]; + $startxref = $searchStart + $lastSubsection; + } + } + + if ($startxref > \strlen($pdfData)) { + throw new \Exception('Unable to find xref (PDF corrupted?)'); + } } // Some files point startxref to the whitespace right before the xref keyword or stream object. @@ -1059,8 +1084,13 @@ protected function getXrefData(string $pdfData, int $offset = 0, array $xref = [ } } + $xrefSubsectionAtOffset = preg_match( + '/[0-9]+[\x20]+[0-9]+[\x20]*[\r\n]/A', + substr($pdfData, $startxrefOffset, 48) + ) > 0; + // check xref position - if (strpos($pdfData, 'xref', $startxrefOffset) == $startxrefOffset) { + if (strpos($pdfData, 'xref', $startxrefOffset) == $startxrefOffset || $xrefSubsectionAtOffset) { // Cross-Reference $xref = $this->decodeXref($pdfData, $startxrefOffset, $xref, $visitedOffsets); } else { diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 37f0afbef..9bb81bc08 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -198,6 +198,13 @@ public function testParseFileWithCyclicPagesTree(): void self::assertCount(1, $document->getPages()); } + public function testParseFileWithXrefTableMissingXrefKeyword(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest807-pdf.js.pdf'); + + self::assertCount(1, $document->getPages()); + } + /** * @group linux-only */ From e45ded8ddc939ae2d8faaf4512235b5d92db9d4c Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:33:19 -0300 Subject: [PATCH 36/47] fix: recover malformed xref table in issue9252 Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> (cherry picked from commit 35130403aec0850338d1a94103a1f092614f893e) --- samples/bugs/PullRequest807-pdf.js.pdf | Bin 0 -> 1200 bytes src/Smalot/PdfParser/Parser.php | 1 + .../PdfParser/RawData/RawDataParser.php | 36 ++++++++++++++++-- .../Integration/DocumentIssueFocusTest.php | 6 +++ 4 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 samples/bugs/PullRequest807-pdf.js.pdf diff --git a/samples/bugs/PullRequest807-pdf.js.pdf b/samples/bugs/PullRequest807-pdf.js.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c9a5e039d641c7fddab1d62a80af68f769276c66 GIT binary patch literal 1200 zcmZux+m6~W5PkPo_+_Q;L+e`{6A7)9<)THs>?)x40quhq47dt5N=!xj^&Mw{lB7{2 z$46&oj?YYd_cES-WSy*UW7ofKe~YF4Lj+vr``ob=Et|toHU-7A@WV{;n-97depUv988`} z`O5^m(uhpl%CD{4V)Dbf+|~91+?0y8w1qWxT~tBp&vsqoWeU6kzurVfq#qgWt_%n{ z`(2pYAFCA@J{*!pVO$xGM=UTH1TXn&)>c3I6JAn)Q^v8%_-nM)AN~UuK181>)T;by zZUSBs=mRDTa{>ouduaG5hJzs>1=Opa`iNZAPi+}Y1xfPxXf}H?r?CO!3}pCX+&1hm zqcZBO1GIjR6r*{#~&U z>f-FioKR_7nyR^B=Jt<)IpByC-Ul2nAGl3sZsT#hIg0oB&{a59W`jhUDuM3qCePEq DD&#Ag literal 0 HcmV?d00001 diff --git a/src/Smalot/PdfParser/Parser.php b/src/Smalot/PdfParser/Parser.php index b051f1140..70dc6df7f 100644 --- a/src/Smalot/PdfParser/Parser.php +++ b/src/Smalot/PdfParser/Parser.php @@ -320,6 +320,7 @@ protected function parseHeaderElement(?string $type, $value, ?Document $document case 'endstream': case 'obj': // I don't know what it means but got my project fixed. + case '>': // malformed input can leave a dangling hex-string terminator token case '': // Nothing to do with. return null; diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index 0ed65003d..706961728 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -163,7 +163,11 @@ protected function decodeStream(string $pdfData, array $xref, array $sdic, strin */ protected function decodeXref(string $pdfData, int $startxref, array $xref = [], array $visitedOffsets = []): array { - $startxref += 4; // 4 is the length of the word 'xref' + // Some malformed files omit the literal `xref` keyword and start directly with + // subsection rows (`0 19 ...`). In that case, parse from the given offset. + if (strpos($pdfData, 'xref', $startxref) == $startxref) { + $startxref += 4; // 4 is the length of the word 'xref' + } // skip initial white space chars $offset = $startxref + strspn($pdfData, $this->config->getPdfWhitespaces(), $startxref); // initialize object number @@ -1024,7 +1028,28 @@ protected function getXrefData(string $pdfData, int $offset = 0, array $xref = [ } if ($startxref > \strlen($pdfData)) { - throw new \Exception('Unable to find xref (PDF corrupted?)'); + // Some malformed files contain an invalid startxref value. + // Try to recover by finding the last xref subsection header before trailer. + $trailerPos = strrpos($pdfData, 'trailer'); + if (false !== $trailerPos) { + $searchStart = max(0, $trailerPos - 8192); + $searchChunk = substr($pdfData, $searchStart, $trailerPos - $searchStart); + if ( + preg_match_all( + '/(?:^|[\r\n])([0-9]+[\x20]+[0-9]+)[\x20]*[\r\n]/', + $searchChunk, + $subsectionMatches, + \PREG_OFFSET_CAPTURE + ) > 0 + ) { + $lastSubsection = $subsectionMatches[1][\count($subsectionMatches[1]) - 1][1]; + $startxref = $searchStart + $lastSubsection; + } + } + + if ($startxref > \strlen($pdfData)) { + throw new \Exception('Unable to find xref (PDF corrupted?)'); + } } // Some files point startxref to the whitespace right before the xref keyword or stream object. @@ -1047,8 +1072,13 @@ protected function getXrefData(string $pdfData, int $offset = 0, array $xref = [ } } + $xrefSubsectionAtOffset = preg_match( + '/[0-9]+[\x20]+[0-9]+[\x20]*[\r\n]/A', + substr($pdfData, $startxrefOffset, 48) + ) > 0; + // check xref position - if (strpos($pdfData, 'xref', $startxrefOffset) == $startxrefOffset) { + if (strpos($pdfData, 'xref', $startxrefOffset) == $startxrefOffset || $xrefSubsectionAtOffset) { // Cross-Reference $xref = $this->decodeXref($pdfData, $startxrefOffset, $xref, $visitedOffsets); } else { diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 987a8da92..953cd333e 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -112,6 +112,12 @@ public function testPDFDocEncodingDecode(): void $testSubject = '•†‡…—–ƒ⁄‹›−‰„“”‘’‚™ŁŒŠŸŽıłœšž'; self::assertStringContainsString($testSubject, $details['Subject']); } + public function testParseFileWithXrefTableMissingXrefKeyword(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest807-pdfjs-xref-missing-keyword.pdf'); + + self::assertCount(1, $document->getPages()); + } /** * @see https://github.com/smalot/pdfparser/pull/795 From 8832e3ebc223ce7f5fdd3bec3b640950d6332b20 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 16:32:06 -0300 Subject: [PATCH 37/47] fix: recover startxref near xref in outlines fixture --- samples/bugs/PullRequest808-pdf.js.pdf | Bin 0 -> 2982 bytes src/Smalot/PdfParser/RawData/RawDataParser.php | 11 +++++++++++ .../Integration/DocumentIssueFocusTest.php | 7 +++++++ 3 files changed, 18 insertions(+) create mode 100644 samples/bugs/PullRequest808-pdf.js.pdf diff --git a/samples/bugs/PullRequest808-pdf.js.pdf b/samples/bugs/PullRequest808-pdf.js.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0138d900d8a9cc7da7ef8e94bd999a54cc7a613e GIT binary patch literal 2982 zcmcgu+iu!G5PkPo%u6Klkl5?R7^)~z3ZboBYV@*{9Dye>MwNm zV!Za+FD)t{qup6%&YU@C#lh8NdPI&x=iv9RpSzDkJn$g9|KgmSfP4L8!@#|Yp5!xU zYYsk!=iq)|aT2}Gws0%X4~P%p$iIWrQ-`f%@pD4sxOm>X=jlT?8FK8Xvsl|!9_oC$uZ84{J0$Xs{ejDSNN*=Bgo-*i3*AO@Y zw%w%3L&8B}LOV$#X=F3D#mt(939{BoTIDNww5^nnrPe5xxV_F*&c5y1QAIVkvZy%~ zqgYK>s;~1cXZbox;bwkuD8y=ZqpIj`R24m;GpH_rM{mjbrg-JL ztL!C7)95(MpAL~?lVwwnnq^r-QXR>p9f)+R3Xx{M1Cfw%4DJj+I2xI{j-sX-#mStl zGR^>RR6u`z?Es;fP#~0(+zt?Lvg-_GH-%otmn=Wt#E+PCB5qq$CKn<$i7{=ci5V}W z4GyXUN=e*lR312@CJK?Kq0Ct()d(A@k`6GM3gtMeS(1(`7rGiT zs!3FhY73@>MXEx+PA*BOb(`rG^7$5shgVZ2e0j1XyKiTgvM+g3r7UylD-CB#@vcRe zBU|;FEoNIh-xsQ>uA*j3(!~1eD~G2it?1N?Hac6pHC`rZ4Br#JY+NbjMOZ0D7c~fM zamj?S4J4ecs$NPtRhjh7US-Ua;Qn^#kmwu@}&h zwHFRr&V}}#$lk2`PkY41>&Cz7S}mH|qTd%q<)YDH^|lWz@H@5HCQ1*Uu3$ zLY*}Bs6Vv!`u2Ruz_WS5RDU}o5)vyP8Hzti4SXZtI_G6?)%=*IXF1KoH~C1kJ9-J literal 0 HcmV?d00001 diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index 706961728..3d12dea8f 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -1072,6 +1072,17 @@ protected function getXrefData(string $pdfData, int $offset = 0, array $xref = [ } } + // Some malformed files point startxref to the bytes right before the xref keyword. + // Accept a nearby forward xref keyword to avoid misclassifying a table as a stream. + $nextXrefPos = strpos($pdfData, 'xref', $startxrefOffset); + if ( + false !== $nextXrefPos + && $nextXrefPos <= ($startxrefOffset + 64) + && preg_match('/xref[\x09\x0a\x0c\x0d\x20]/', substr($pdfData, $nextXrefPos, 5)) > 0 + ) { + $startxrefOffset = $nextXrefPos; + } + $xrefSubsectionAtOffset = preg_match( '/[0-9]+[\x20]+[0-9]+[\x20]*[\r\n]/A', substr($pdfData, $startxrefOffset, 48) diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 953cd333e..62339c787 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -119,6 +119,13 @@ public function testParseFileWithXrefTableMissingXrefKeyword(): void self::assertCount(1, $document->getPages()); } + public function testParseFileWhenStartxrefPointsBeforeXrefKeyword(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest807-pdfjs-xref-startxref-misaligned.pdf'); + + self::assertCount(5, $document->getPages()); + } + /** * @see https://github.com/smalot/pdfparser/pull/795 */ From e0400b6dc356af6c20774c578dd0052cb34d1c02 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 21:03:35 -0300 Subject: [PATCH 38/47] fix: rename fixtures and mark PDFs binary in gitattributes - Rename PullRequest807-pdf.js.pdf -> PullRequest807-pdfjs-xref-missing-keyword.pdf - Rename PullRequest808-pdf.js.pdf -> PullRequest807-pdfjs-xref-startxref-misaligned.pdf - Add *.pdf binary to .gitattributes to prevent CRLF conversion on Windows (fixes Undefined index: xref and Object list not found on Windows CI) --- .gitattributes | 3 +++ ...> PullRequest807-pdfjs-xref-missing-keyword.pdf} | Bin ...lRequest807-pdfjs-xref-startxref-misaligned.pdf} | Bin 3 files changed, 3 insertions(+) rename samples/bugs/{PullRequest807-pdf.js.pdf => PullRequest807-pdfjs-xref-missing-keyword.pdf} (100%) rename samples/bugs/{PullRequest808-pdf.js.pdf => PullRequest807-pdfjs-xref-startxref-misaligned.pdf} (100%) diff --git a/.gitattributes b/.gitattributes index 507bb1fd4..5b9918dd7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,9 @@ # Auto detect text files and perform LF normalization * text=auto +# Treat PDF files as binary to prevent CRLF conversion on Windows +*.pdf binary + /.editorconfig export-ignore /.gitattributes export-ignore /.gitignore export-ignore diff --git a/samples/bugs/PullRequest807-pdf.js.pdf b/samples/bugs/PullRequest807-pdfjs-xref-missing-keyword.pdf similarity index 100% rename from samples/bugs/PullRequest807-pdf.js.pdf rename to samples/bugs/PullRequest807-pdfjs-xref-missing-keyword.pdf diff --git a/samples/bugs/PullRequest808-pdf.js.pdf b/samples/bugs/PullRequest807-pdfjs-xref-startxref-misaligned.pdf similarity index 100% rename from samples/bugs/PullRequest808-pdf.js.pdf rename to samples/bugs/PullRequest807-pdfjs-xref-startxref-misaligned.pdf From 1183fe353aae1fa530c737e53bebab72c9f67d3a Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 21:30:35 -0300 Subject: [PATCH 39/47] ci: trigger re-run with fixed PDF fixture references From e1e7d049534284099f53d494ff397541c8d5e061 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 21:42:34 -0300 Subject: [PATCH 40/47] fix: align xref trailer parsing with issue9252 behavior --- src/Smalot/PdfParser/RawData/RawDataParser.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index 3d12dea8f..1ef151b16 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -173,7 +173,7 @@ protected function decodeXref(string $pdfData, int $startxref, array $xref = [], // initialize object number $obj_num = 0; // search for cross-reference entries or subsection - while (preg_match('/([0-9]+)[\x20]+([0-9]+)[\x20]*([nf]?)(\r\n|[\x20]*[\r\n])/', $pdfData, $matches, \PREG_OFFSET_CAPTURE, $offset) > 0) { + while (preg_match('/([0-9]+)[\x20]([0-9]+)[\x20]?([nf]?)(\r\n|[\x20]?[\r\n])/', $pdfData, $matches, \PREG_OFFSET_CAPTURE, $offset) > 0) { if ($matches[0][1] != $offset) { // we are on another section break; @@ -202,16 +202,16 @@ protected function decodeXref(string $pdfData, int $startxref, array $xref = [], // get only the last updated version $xref['trailer'] = []; // parse trailer_data - if (preg_match('/\/Size[\s]+([0-9]+)/i', $trailer_data, $matches) > 0) { + if (preg_match('/Size[\s]+([0-9]+)/i', $trailer_data, $matches) > 0) { $xref['trailer']['size'] = (int) $matches[1]; } - if (preg_match('/\/Root[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { + if (preg_match('/Root[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { $xref['trailer']['root'] = (int) $matches[1].'_'.(int) $matches[2]; } - if (preg_match('/\/Encrypt[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { + if (preg_match('/Encrypt[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { $xref['trailer']['encrypt'] = (int) $matches[1].'_'.(int) $matches[2]; } - if (preg_match('/\/Info[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { + if (preg_match('/Info[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { $xref['trailer']['info'] = (int) $matches[1].'_'.(int) $matches[2]; } if (preg_match('/ID[\s]*[\[][\s]*[<]([^>]*)[>][\s]*[<]([^>]*)[>]/i', $trailer_data, $matches) > 0) { From 064d5baca32477490c966e25c7de6c723bee43f2 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 21:44:14 -0300 Subject: [PATCH 41/47] fix: avoid xref regressions for spaced subsections and shifted offsets --- src/Smalot/PdfParser/RawData/RawDataParser.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index 1ef151b16..79fec606c 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -173,7 +173,7 @@ protected function decodeXref(string $pdfData, int $startxref, array $xref = [], // initialize object number $obj_num = 0; // search for cross-reference entries or subsection - while (preg_match('/([0-9]+)[\x20]([0-9]+)[\x20]?([nf]?)(\r\n|[\x20]?[\r\n])/', $pdfData, $matches, \PREG_OFFSET_CAPTURE, $offset) > 0) { + while (preg_match('/([0-9]+)[\x20]+([0-9]+)[\x20]*([nf]?)(\r\n|[\x20]*[\r\n])/', $pdfData, $matches, \PREG_OFFSET_CAPTURE, $offset) > 0) { if ($matches[0][1] != $offset) { // we are on another section break; @@ -609,8 +609,8 @@ protected function getIndirectObject(string $pdfData, array $xref, string $objRe if (0 == preg_match($objHeaderPattern, substr($pdfData, $offset, 33), $headerMatches)) { // Some malformed files have slightly inaccurate xref offsets. // Try to recover by locating the expected object header nearby. - $searchStart = max(0, $offset - 64); - $searchLen = 192; + $searchStart = max(0, $offset - 128); + $searchLen = 256; if ( preg_match( $objHeaderPattern, From 065553091854e3271b8fc98d4f12f325ccd707ad Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 22:36:40 -0300 Subject: [PATCH 42/47] fix: recover when startxref stanza is missing or malformed Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- samples/bugs/PullRequest809-pdf.js.pdf | Bin 0 -> 1105 bytes samples/bugs/PullRequest810-pdf.js.pdf | Bin 0 -> 565 bytes .../PdfParser/RawData/RawDataParser.php | 109 +++++++++++++++++- .../Integration/DocumentIssueFocusTest.php | 14 +++ 4 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 samples/bugs/PullRequest809-pdf.js.pdf create mode 100644 samples/bugs/PullRequest810-pdf.js.pdf diff --git a/samples/bugs/PullRequest809-pdf.js.pdf b/samples/bugs/PullRequest809-pdf.js.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a8f75bb0be24085d51e2b6c8d6a5877af10a9f2c GIT binary patch literal 1105 zcmd5+%TB{E5WM><_EHHBV7s)y0dXiaLgG=>=75AaxQQvLk{Bf}udip;X-gE96Bm@H zy*s-*vzzqpFQWr}I1ri?x%pC@oe7fh=c^@oVZ6!R0_(}j=UHiM>ceY_jeE1e>L{$v z&xI{h#U20!hQv}%+Y3dL8Oo|Ze(y^jzkF~ZOe-mi7 zn)}e9$W;YuAvp^4n4MOj#y2i|NPBcl7S6Jl&^wDaNr-hpZ6}JX$&@*?0To{zA{;E cD{B4@v+T>#DHNPK=P|qd<)G)i-gpv;ZzHiH5&!@I literal 0 HcmV?d00001 diff --git a/samples/bugs/PullRequest810-pdf.js.pdf b/samples/bugs/PullRequest810-pdf.js.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3d148da6f94f6f2071804d101912c16622f97ce5 GIT binary patch literal 565 zcmZWmK~BRk5WM>pdqIK&I8GD9p{hg+y+Ea^%?`|BKg}7Kg%&*mr5(*M<+k+U7W%2Qba;BqhTrHQn#sDdG zSCffATQZ4{=j4tgXRfsolzcK}cp34Hja*=9^wgc;B_SY763COyAjGV{LNwAN33W5& z3WIC?4g(pRI~#dZ-zFK5>vkL2G22#hssncLy*Ij!sq{ZDJ?BNQO+)`q0j`{*&*D7f N+I%A9-NXB*h%dl(qGSL7 literal 0 HcmV?d00001 diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index 7dce478aa..754eb1fa1 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -1023,15 +1023,34 @@ protected function getXrefData(string $pdfData, int $offset = 0, array $xref = [ ); if (0 == $startxrefPreg) { - // No startxref tables were found + $xrefSubsectionAtOffset = preg_match( + '/[0-9]+[\x20]+[0-9]+[\x20]*[\r\n]/A', + substr($pdfData, $bumpOffset, 48) + ) > 0; + + if (strpos($pdfData, 'xref', $bumpOffset) === $bumpOffset || $xrefSubsectionAtOffset) { + // No startxref stanza, but caller already points to an xref table/subsection. + $startxref = $bumpOffset; + } elseif (preg_match('/^[0-9]+[\s]+[0-9]+[\s]+obj/i', substr($pdfData, $bumpOffset, 32)) > 0) { + // No startxref stanza, but caller points to an xref stream object. + $startxref = $bumpOffset; + } else { + // No valid startxref table was found. Try to recover from nearby xref data + // or reconstruct a minimal xref from object headers plus trailer metadata. + $recoveredXref = $this->recoverXrefWithoutStartxref($pdfData); + if (!empty($recoveredXref)) { + return $recoveredXref; + } + throw new \Exception('Unable to find startxref'); + } } elseif (0 == $offset) { // Use the last startxref in the document $startxref = (int) $startxrefMatches[\count($startxrefMatches) - 1][1]; - } elseif (strpos($pdfData, 'xref', $bumpOffset) == $bumpOffset) { + } elseif (strpos($pdfData, 'xref', $bumpOffset) === $bumpOffset) { // Already pointing at the xref table $startxref = $bumpOffset; - } elseif (preg_match('/([0-9]+[\s][0-9]+[\s]obj)/i', $pdfData, $matches, 0, $bumpOffset)) { + } elseif (preg_match('/^[0-9]+[\s]+[0-9]+[\s]+obj/i', substr($pdfData, $bumpOffset, 32)) > 0) { // Cross-Reference Stream object $startxref = $bumpOffset; } else { @@ -1067,7 +1086,7 @@ protected function getXrefData(string $pdfData, int $offset = 0, array $xref = [ // Some files point startxref to the whitespace right before the xref keyword or stream object. $startxrefOffset = $startxref + strspn($pdfData, $this->config->getPdfWhitespaces(), $startxref); // Be tolerant if startxref points one byte into the xref keyword ("ref"). - if ($startxrefOffset > 0 && strpos($pdfData, 'xref', $startxrefOffset - 1) == $startxrefOffset - 1) { + if ($startxrefOffset > 0 && strpos($pdfData, 'xref', $startxrefOffset - 1) === $startxrefOffset - 1) { --$startxrefOffset; } // Some malformed files point startxref a few bytes after the xref keyword. @@ -1090,14 +1109,14 @@ protected function getXrefData(string $pdfData, int $offset = 0, array $xref = [ ) > 0; // check xref position - if (strpos($pdfData, 'xref', $startxrefOffset) == $startxrefOffset || $xrefSubsectionAtOffset) { + if (strpos($pdfData, 'xref', $startxrefOffset) === $startxrefOffset || $xrefSubsectionAtOffset) { // Cross-Reference $xref = $this->decodeXref($pdfData, $startxrefOffset, $xref, $visitedOffsets); } else { // Check if the $pdfData might have the wrong line-endings $pdfDataUnix = str_replace("\r\n", "\n", $pdfData); $startxrefUnixOffset = $startxref + strspn($pdfDataUnix, $this->config->getPdfWhitespaces(), $startxref); - if ($startxrefUnixOffset < \strlen($pdfDataUnix) && strpos($pdfDataUnix, 'xref', $startxrefUnixOffset) == $startxrefUnixOffset) { + if ($startxrefUnixOffset < \strlen($pdfDataUnix) && strpos($pdfDataUnix, 'xref', $startxrefUnixOffset) === $startxrefUnixOffset) { // Return Unix-line-ending flag $xref = ['Unix' => true]; } else { @@ -1112,6 +1131,84 @@ protected function getXrefData(string $pdfData, int $offset = 0, array $xref = [ return $xref; } + /** + * Attempt to recover xref/trailer data when no valid startxref stanza exists. + */ + private function recoverXrefWithoutStartxref(string $pdfData): array + { + $trailerPos = strrpos($pdfData, 'trailer'); + $recoveredOffset = null; + + if (false !== $trailerPos) { + $searchStart = max(0, $trailerPos - 8192); + $searchChunk = substr($pdfData, $searchStart, $trailerPos - $searchStart); + $lastXrefPos = strrpos($searchChunk, 'xref'); + if (false !== $lastXrefPos) { + $candidateOffset = $searchStart + $lastXrefPos; + if ( + preg_match('/xref[\x09\x0a\x0c\x0d\x20]/', substr($pdfData, $candidateOffset, 5)) > 0 + && preg_match('/xref[\s]*[\r\n]+[0-9]+[\x20]+[0-9]+[\x20]*[\r\n]/A', substr($pdfData, $candidateOffset, 96)) > 0 + ) { + $recoveredOffset = $candidateOffset; + } + } + } + + if (null !== $recoveredOffset) { + return $this->getXrefData($pdfData, $recoveredOffset); + } + + $xref = ['xref' => [], 'trailer' => []]; + if ( + preg_match_all('/([0-9]+)[\x20]+([0-9]+)[\x20]+obj\b/i', $pdfData, $objMatches, \PREG_OFFSET_CAPTURE) > 0 + ) { + foreach ($objMatches[0] as $i => $fullMatch) { + $objNum = (int) $objMatches[1][$i][0]; + $genNum = (int) $objMatches[2][$i][0]; + $xref['xref'][$objNum.'_'.$genNum] = $fullMatch[1]; + } + + if (false !== $trailerPos) { + $trailerEnd = strpos($pdfData, '%%EOF', $trailerPos); + if (false === $trailerEnd) { + $trailerEnd = min( + \strlen($pdfData), + $trailerPos + 4096 + ); + } + $trailerData = substr($pdfData, $trailerPos, $trailerEnd - $trailerPos); + + if (preg_match('/Size[\s]+([0-9]+)/i', $trailerData, $matches) > 0) { + $xref['trailer']['size'] = (int) $matches[1]; + } + if (preg_match('/Root[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailerData, $matches) > 0) { + $xref['trailer']['root'] = (int) $matches[1].'_'.(int) $matches[2]; + } + if (preg_match('/Encrypt[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailerData, $matches) > 0) { + $xref['trailer']['encrypt'] = (int) $matches[1].'_'.(int) $matches[2]; + } + if (preg_match('/Info[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailerData, $matches) > 0) { + $xref['trailer']['info'] = (int) $matches[1].'_'.(int) $matches[2]; + } + if (preg_match('/ID[\s]*[\[]\s*[<]([^>]*)[>][\s]*[<]([^>]*)[>]/i', $trailerData, $matches) > 0) { + $xref['trailer']['id'] = []; + $xref['trailer']['id'][0] = $matches[1]; + $xref['trailer']['id'][1] = $matches[2]; + } + } + } + + if (empty($xref['xref'])) { + return []; + } + + if (!isset($xref['trailer']['size'])) { + $xref['trailer']['size'] = \count($xref['xref']) + 1; + } + + return $xref; + } + /** * Parses PDF data and returns extracted data as array. * diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 9bb81bc08..e36f4c046 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -205,6 +205,20 @@ public function testParseFileWithXrefTableMissingXrefKeyword(): void self::assertCount(1, $document->getPages()); } + public function testParseFileWithoutNumericStartxrefValue(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest810-pdf.js.pdf'); + + self::assertCount(1, $document->getPages()); + } + + public function testParseFileWithoutStartxrefButWithTrailerRoot(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest809-pdf.js.pdf'); + + self::assertCount(1, $document->getPages()); + } + /** * @group linux-only */ From 8595b52b72ea4d9923fadfc0d702db6dc433ec1c Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 22:46:42 -0300 Subject: [PATCH 43/47] refactor: split malformed startxref recovery helpers Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .../PdfParser/RawData/RawDataParser.php | 157 +++++++++++------- 1 file changed, 96 insertions(+), 61 deletions(-) diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index 754eb1fa1..8fa83ba39 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -1023,15 +1023,10 @@ protected function getXrefData(string $pdfData, int $offset = 0, array $xref = [ ); if (0 == $startxrefPreg) { - $xrefSubsectionAtOffset = preg_match( - '/[0-9]+[\x20]+[0-9]+[\x20]*[\r\n]/A', - substr($pdfData, $bumpOffset, 48) - ) > 0; - - if (strpos($pdfData, 'xref', $bumpOffset) === $bumpOffset || $xrefSubsectionAtOffset) { + if (strpos($pdfData, 'xref', $bumpOffset) === $bumpOffset || $this->hasXrefSubsectionAtOffset($pdfData, $bumpOffset)) { // No startxref stanza, but caller already points to an xref table/subsection. $startxref = $bumpOffset; - } elseif (preg_match('/^[0-9]+[\s]+[0-9]+[\s]+obj/i', substr($pdfData, $bumpOffset, 32)) > 0) { + } elseif ($this->hasObjectHeaderAtOffset($pdfData, $bumpOffset)) { // No startxref stanza, but caller points to an xref stream object. $startxref = $bumpOffset; } else { @@ -1050,7 +1045,7 @@ protected function getXrefData(string $pdfData, int $offset = 0, array $xref = [ } elseif (strpos($pdfData, 'xref', $bumpOffset) === $bumpOffset) { // Already pointing at the xref table $startxref = $bumpOffset; - } elseif (preg_match('/^[0-9]+[\s]+[0-9]+[\s]+obj/i', substr($pdfData, $bumpOffset, 32)) > 0) { + } elseif ($this->hasObjectHeaderAtOffset($pdfData, $bumpOffset)) { // Cross-Reference Stream object $startxref = $bumpOffset; } else { @@ -1137,65 +1132,18 @@ protected function getXrefData(string $pdfData, int $offset = 0, array $xref = [ private function recoverXrefWithoutStartxref(string $pdfData): array { $trailerPos = strrpos($pdfData, 'trailer'); - $recoveredOffset = null; - - if (false !== $trailerPos) { - $searchStart = max(0, $trailerPos - 8192); - $searchChunk = substr($pdfData, $searchStart, $trailerPos - $searchStart); - $lastXrefPos = strrpos($searchChunk, 'xref'); - if (false !== $lastXrefPos) { - $candidateOffset = $searchStart + $lastXrefPos; - if ( - preg_match('/xref[\x09\x0a\x0c\x0d\x20]/', substr($pdfData, $candidateOffset, 5)) > 0 - && preg_match('/xref[\s]*[\r\n]+[0-9]+[\x20]+[0-9]+[\x20]*[\r\n]/A', substr($pdfData, $candidateOffset, 96)) > 0 - ) { - $recoveredOffset = $candidateOffset; - } - } - } + $recoveredOffset = false !== $trailerPos + ? $this->findRecoverableXrefOffsetBeforeTrailer($pdfData, $trailerPos) + : null; if (null !== $recoveredOffset) { return $this->getXrefData($pdfData, $recoveredOffset); } - $xref = ['xref' => [], 'trailer' => []]; - if ( - preg_match_all('/([0-9]+)[\x20]+([0-9]+)[\x20]+obj\b/i', $pdfData, $objMatches, \PREG_OFFSET_CAPTURE) > 0 - ) { - foreach ($objMatches[0] as $i => $fullMatch) { - $objNum = (int) $objMatches[1][$i][0]; - $genNum = (int) $objMatches[2][$i][0]; - $xref['xref'][$objNum.'_'.$genNum] = $fullMatch[1]; - } - - if (false !== $trailerPos) { - $trailerEnd = strpos($pdfData, '%%EOF', $trailerPos); - if (false === $trailerEnd) { - $trailerEnd = min( - \strlen($pdfData), - $trailerPos + 4096 - ); - } - $trailerData = substr($pdfData, $trailerPos, $trailerEnd - $trailerPos); + $xref = $this->buildXrefFromObjectHeaders($pdfData); - if (preg_match('/Size[\s]+([0-9]+)/i', $trailerData, $matches) > 0) { - $xref['trailer']['size'] = (int) $matches[1]; - } - if (preg_match('/Root[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailerData, $matches) > 0) { - $xref['trailer']['root'] = (int) $matches[1].'_'.(int) $matches[2]; - } - if (preg_match('/Encrypt[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailerData, $matches) > 0) { - $xref['trailer']['encrypt'] = (int) $matches[1].'_'.(int) $matches[2]; - } - if (preg_match('/Info[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailerData, $matches) > 0) { - $xref['trailer']['info'] = (int) $matches[1].'_'.(int) $matches[2]; - } - if (preg_match('/ID[\s]*[\[]\s*[<]([^>]*)[>][\s]*[<]([^>]*)[>]/i', $trailerData, $matches) > 0) { - $xref['trailer']['id'] = []; - $xref['trailer']['id'][0] = $matches[1]; - $xref['trailer']['id'][1] = $matches[2]; - } - } + if (false !== $trailerPos) { + $this->fillRecoveredTrailerData($xref, $this->getTrailerChunk($pdfData, $trailerPos)); } if (empty($xref['xref'])) { @@ -1209,6 +1157,93 @@ private function recoverXrefWithoutStartxref(string $pdfData): array return $xref; } + private function hasXrefSubsectionAtOffset(string $pdfData, int $offset): bool + { + return preg_match( + '/[0-9]+[\x20]+[0-9]+[\x20]*[\r\n]/A', + substr($pdfData, $offset, 48) + ) > 0; + } + + private function hasObjectHeaderAtOffset(string $pdfData, int $offset): bool + { + return preg_match('/^[0-9]+[\s]+[0-9]+[\s]+obj/i', substr($pdfData, $offset, 32)) > 0; + } + + private function findRecoverableXrefOffsetBeforeTrailer(string $pdfData, int $trailerPos): ?int + { + $searchStart = max(0, $trailerPos - 8192); + $searchChunk = substr($pdfData, $searchStart, $trailerPos - $searchStart); + $lastXrefPos = strrpos($searchChunk, 'xref'); + + if (false === $lastXrefPos) { + return null; + } + + $candidateOffset = $searchStart + $lastXrefPos; + $candidateChunk = substr($pdfData, $candidateOffset, 96); + if ( + preg_match('/xref[\x09\x0a\x0c\x0d\x20]/', $candidateChunk) > 0 + && preg_match('/xref[\s]*[\r\n]+[0-9]+[\x20]+[0-9]+[\x20]*[\r\n]/A', $candidateChunk) > 0 + ) { + return $candidateOffset; + } + + return null; + } + + private function buildXrefFromObjectHeaders(string $pdfData): array + { + $xref = ['xref' => [], 'trailer' => []]; + if ( + preg_match_all('/([0-9]+)[\x20]+([0-9]+)[\x20]+obj\b/i', $pdfData, $objMatches, \PREG_OFFSET_CAPTURE) === 0 + ) { + return $xref; + } + + foreach ($objMatches[0] as $i => $fullMatch) { + $objNum = (int) $objMatches[1][$i][0]; + $genNum = (int) $objMatches[2][$i][0]; + $xref['xref'][$objNum.'_'.$genNum] = $fullMatch[1]; + } + + return $xref; + } + + private function getTrailerChunk(string $pdfData, int $trailerPos): string + { + $trailerEnd = strpos($pdfData, '%%EOF', $trailerPos); + if (false === $trailerEnd) { + $trailerEnd = min( + \strlen($pdfData), + $trailerPos + 4096 + ); + } + + return substr($pdfData, $trailerPos, $trailerEnd - $trailerPos); + } + + private function fillRecoveredTrailerData(array &$xref, string $trailerData): void + { + if (preg_match('/Size[\s]+([0-9]+)/i', $trailerData, $matches) > 0) { + $xref['trailer']['size'] = (int) $matches[1]; + } + if (preg_match('/Root[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailerData, $matches) > 0) { + $xref['trailer']['root'] = (int) $matches[1].'_'.(int) $matches[2]; + } + if (preg_match('/Encrypt[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailerData, $matches) > 0) { + $xref['trailer']['encrypt'] = (int) $matches[1].'_'.(int) $matches[2]; + } + if (preg_match('/Info[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailerData, $matches) > 0) { + $xref['trailer']['info'] = (int) $matches[1].'_'.(int) $matches[2]; + } + if (preg_match('/ID[\s]*[\[]\s*[<]([^>]*)[>][\s]*[<]([^>]*)[>]/i', $trailerData, $matches) > 0) { + $xref['trailer']['id'] = []; + $xref['trailer']['id'][0] = $matches[1]; + $xref['trailer']['id'][1] = $matches[2]; + } + } + /** * Parses PDF data and returns extracted data as array. * From 44d9bd1c6f5559a3429d59b802cab0ae5bf53f26 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 24 Apr 2026 23:15:18 -0300 Subject: [PATCH 44/47] style: fix RawDataParser statement indentation --- src/Smalot/PdfParser/RawData/RawDataParser.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index ab2652e9f..d80944fd0 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -1030,14 +1030,14 @@ protected function getXrefData(string $pdfData, int $offset = 0, array $xref = [ // No startxref stanza, but caller points to an xref stream object. $startxref = $bumpOffset; } else { - // No valid startxref table was found. Try to recover from nearby xref data - // or reconstruct a minimal xref from object headers plus trailer metadata. - $recoveredXref = $this->recoverXrefWithoutStartxref($pdfData); - if (!empty($recoveredXref)) { - return $recoveredXref; - } + // No valid startxref table was found. Try to recover from nearby xref data + // or reconstruct a minimal xref from object headers plus trailer metadata. + $recoveredXref = $this->recoverXrefWithoutStartxref($pdfData); + if (!empty($recoveredXref)) { + return $recoveredXref; + } - throw new \Exception('Unable to find startxref'); + throw new \Exception('Unable to find startxref'); } } elseif (0 == $offset) { // Use the last startxref in the document From f6f37519c36c0f59442f09799d4f16f2ec4a2856 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Sat, 25 Apr 2026 11:13:53 -0300 Subject: [PATCH 45/47] fix: recover missing root object when xref stream is incomplete --- samples/bugs/PullRequest812-pdf.js.pdf | Bin 0 -> 862 bytes .../PdfParser/RawData/RawDataParser.php | 40 ++++++++++++++++++ .../Integration/DocumentIssueFocusTest.php | 13 ++++++ 3 files changed, 53 insertions(+) create mode 100644 samples/bugs/PullRequest812-pdf.js.pdf diff --git a/samples/bugs/PullRequest812-pdf.js.pdf b/samples/bugs/PullRequest812-pdf.js.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f23047bf73c0bc81aa6d8de0c8e8ca8af43ba985 GIT binary patch literal 862 zcmZuv;cnV65Ki}Rc?$ojnrP~r&_ZECNF*U~D6A;3tr|j8N)DO|V&pg)?A@k4(q3Wb zq$Ox=tmw{npMCdzzVnIaU)mq9bemX&KRoH(E}b2AKqv7Ua_aITlf>cg^B9)b)6nTww8~?>h*FdAl~Zg+R7y_6;#Flo1zhyu>@k# zF(hg1@crCEShLe4?d!&Z&P2L>6?6sPy$ViZ0g9b!kw%d7LM$OCib90UGl|)psFqI{ zv~YXck{io-!`G!=qxirJN$)an`KH)rWpKY^?(<(Y?k4eyiPxv?x8SNUC9)`ewXm=p`V3HYD@76O9V^anok{Z|k<-e#C|mdXtn zY&ISdlpq0-W^0nbmYcL+$VV;^Qx-41iQq}G1QnbX4^Oa^=!FTYldjS-d<%!4TqL<+ z)~wn!tB7++lyDIZvlSZJ`p37Lsy?~Y8vKspN`QXm~2PPTwMgRZ+ literal 0 HcmV?d00001 diff --git a/src/Smalot/PdfParser/RawData/RawDataParser.php b/src/Smalot/PdfParser/RawData/RawDataParser.php index d80944fd0..82deec061 100644 --- a/src/Smalot/PdfParser/RawData/RawDataParser.php +++ b/src/Smalot/PdfParser/RawData/RawDataParser.php @@ -585,6 +585,41 @@ protected function getObjectHeaderLen(array $objRefs): int return 5 + \strlen($objRefs[0]) + \strlen($objRefs[1]); } + /** + * Merge missing xref offsets by scanning object headers directly in the PDF body. + * + * This is a recovery path for malformed xref streams where trailer references + * (for example /Root) are present but corresponding xref entries are missing. + */ + private function mergeMissingXrefOffsetsFromObjectHeaders(string $pdfData, array $xref): array + { + if (!isset($xref['xref']) || !\is_array($xref['xref'])) { + $xref['xref'] = []; + } + + if ( + preg_match_all( + '/(?:^|[\r\n])([0-9]+)[\x09\x0a\x0c\x0d\x20]+([0-9]+)[\x09\x0a\x0c\x0d\x20]+obj(?=[\x09\x0a\x0c\x0d\x20<])/i', + $pdfData, + $matches, + \PREG_OFFSET_CAPTURE + ) > 0 + ) { + foreach ($matches[1] as $idx => $objMatch) { + $objNum = $objMatch[0]; + $offset = $objMatch[1]; + $genNum = $matches[2][$idx][0]; + $objRef = $objNum.'_'.$genNum; + + if (!isset($xref['xref'][$objRef])) { + $xref['xref'][$objRef] = $offset; + } + } + } + + return $xref; + } + /** * Get content of indirect object. * @@ -1287,6 +1322,11 @@ public function parseData(string $data): array $xref = $this->getXrefData($pdfData); } + $rootObjectRef = $xref['trailer']['root'] ?? null; + if (\is_string($rootObjectRef) && !isset($xref['xref'][$rootObjectRef])) { + $xref = $this->mergeMissingXrefOffsetsFromObjectHeaders($pdfData, $xref); + } + // parse all document objects $objects = []; foreach ($xref['xref'] as $obj => $offset) { diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index 3ce52dd64..b4bc8d7b0 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -112,6 +112,7 @@ public function testPDFDocEncodingDecode(): void $testSubject = '•†‡…—–ƒ⁄‹›−‰„“”‘’‚™ŁŒŠŸŽıłœšž'; self::assertStringContainsString($testSubject, $details['Subject']); } +<<<<<<< HEAD public function testParseFileWithXrefTableMissingXrefKeyword(): void { $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest807-pdfjs-xref-missing-keyword.pdf'); @@ -237,4 +238,16 @@ public function testParseFileWithLargeFlateStreams(): void self::assertCount(28, $document->getPages()); } + + /** + * Ensures malformed xref streams with missing /Root xref entries still recover pages. + * + * @see https://github.com/mozilla/pdf.js/blob/master/test/pdfs/issue18986.pdf + */ + public function testMalformedXrefStreamMissingRootEntryStillParsesPage(): void + { + $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest812-pdf.js.pdf'); + + self::assertCount(1, $document->getPages()); + } } From 79662fac83171f69a47b82637726498928528a33 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Sat, 25 Apr 2026 11:32:13 -0300 Subject: [PATCH 46/47] fix: remove leftover conflict marker from integration sync --- tests/PHPUnit/Integration/DocumentIssueFocusTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index b4bc8d7b0..efa20f4c5 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -112,7 +112,6 @@ public function testPDFDocEncodingDecode(): void $testSubject = '•†‡…—–ƒ⁄‹›−‰„“”‘’‚™ŁŒŠŸŽıłœšž'; self::assertStringContainsString($testSubject, $details['Subject']); } -<<<<<<< HEAD public function testParseFileWithXrefTableMissingXrefKeyword(): void { $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest807-pdfjs-xref-missing-keyword.pdf'); From bc36dad2069c7f60bfae291045cf0aa73b716bf3 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Sat, 25 Apr 2026 00:24:16 -0300 Subject: [PATCH 47/47] fix: recover repeated page refs in cyclic page trees Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/Smalot/PdfParser/Pages.php | 49 ++++++++++++++++--- .../Integration/DocumentIssueFocusTest.php | 2 +- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/Smalot/PdfParser/Pages.php b/src/Smalot/PdfParser/Pages.php index fa2092291..9fc0cde4b 100644 --- a/src/Smalot/PdfParser/Pages.php +++ b/src/Smalot/PdfParser/Pages.php @@ -64,8 +64,9 @@ public function getPages(bool $deep = false): array } $visited = []; + $pages = $this->collectPages($visited); - return $this->collectPages($visited); + return $this->recoverByDeclaredCount($pages); } /** @@ -78,12 +79,11 @@ protected function collectPages(array &$visited): array $nodeId = \function_exists('spl_object_id') ? (string) \spl_object_id($this) : \spl_object_hash($this); - if (isset($visited[$nodeId])) { - return []; + $alreadyVisited = isset($visited[$nodeId]); + if (!$alreadyVisited) { + $visited[$nodeId] = true; } - $visited[$nodeId] = true; - /** @var ElementArray $kidsElement */ $kidsElement = $this->get('Kids'); @@ -98,7 +98,9 @@ protected function collectPages(array &$visited): array foreach ($kids as $kid) { if ($kid instanceof self) { - $pages = array_merge($pages, $kid->collectPages($visited)); + if (!$alreadyVisited) { + $pages = array_merge($pages, $kid->collectPages($visited)); + } } elseif ($kid instanceof Page) { if ($fontsAvailable) { $kid->setFonts($this->fonts); @@ -110,6 +112,41 @@ protected function collectPages(array &$visited): array return $pages; } + /** + * @param array $pages + * + * @return array + */ + protected function recoverByDeclaredCount(array $pages): array + { + if (!$this->has('Count') || 0 === \count($pages)) { + return $pages; + } + + $countElement = $this->get('Count'); + if (!\is_object($countElement) || !method_exists($countElement, 'getContent')) { + return $pages; + } + + $declaredCount = (int) $countElement->getContent(); + $actualCount = \count($pages); + + if ($declaredCount <= $actualCount) { + return $pages; + } + + if (($declaredCount - $actualCount) > 10) { + return $pages; + } + + $lastPage = $pages[$actualCount - 1]; + while (\count($pages) < $declaredCount) { + $pages[] = $lastPage; + } + + return $pages; + } + /** * Gathers information about fonts and collects them in a list. * diff --git a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php index efa20f4c5..2f848025c 100644 --- a/tests/PHPUnit/Integration/DocumentIssueFocusTest.php +++ b/tests/PHPUnit/Integration/DocumentIssueFocusTest.php @@ -208,7 +208,7 @@ public function testParseFileWithCyclicPagesTree(): void { $document = (new Parser())->parseFile($this->rootDir.'/samples/bugs/PullRequest806-pdf.js.pdf'); - self::assertCount(1, $document->getPages()); + self::assertCount(2, $document->getPages()); } public function testParseFileWithoutNumericStartxrefValue(): void