MDL-86353 mod_assign: Sync exception handling in PdfType and PdfReader

This commit is contained in:
yusufwib01
2025-09-30 09:24:29 +07:00
committed by Huong Nguyen
parent ccb94debcf
commit 321f20bde4
2 changed files with 34 additions and 9 deletions
@@ -27,22 +27,33 @@ class PdfType
* @param PdfType $value
* @param PdfParser $parser
* @param bool $stopAtIndirectObject
* @param array $ensuredObjectsList A list of all ensured indirect objects to prevent recursion
* @return PdfType
* @throws CrossReferenceException
* @throws PdfParserException
*/
public static function resolve(PdfType $value, PdfParser $parser, $stopAtIndirectObject = false)
{
public static function resolve(
PdfType $value,
PdfParser $parser,
$stopAtIndirectObject = false,
array &$ensuredObjectsList = []
) {
if ($value instanceof PdfIndirectObjectReference) {
$value = $parser->getIndirectObject($value->value);
}
if ($value instanceof PdfIndirectObject) {
if ($stopAtIndirectObject === true) {
return $value;
}
return self::resolve($value->value, $parser, $stopAtIndirectObject);
}
if ($value instanceof PdfIndirectObjectReference) {
return self::resolve($parser->getIndirectObject($value->value), $parser, $stopAtIndirectObject);
if (\in_array($value->objectNumber, $ensuredObjectsList, true)) {
throw new PdfParserException(
\sprintf('Indirect reference recursion detected (%s).', $value->objectNumber)
);
}
$ensuredObjectsList[] = $value->objectNumber;
return self::resolve($value->value, $parser, $stopAtIndirectObject, $ensuredObjectsList);
}
return $value;
@@ -139,12 +139,19 @@ class PdfReader
$page = $this->pages[$pageNumber - 1];
if ($page instanceof PdfIndirectObjectReference) {
$readPages = function ($kids) use (&$readPages) {
$alreadyReadKids = [];
$readPages = function ($kids) use (&$readPages, &$alreadyReadKids) {
$kids = PdfArray::ensure($kids);
/** @noinspection LoopWhichDoesNotLoopInspection */
foreach ($kids->value as $reference) {
$reference = PdfIndirectObjectReference::ensure($reference);
if (\in_array($reference->value, $alreadyReadKids, true)) {
throw new PdfReaderException('Recursive pages dictionary detected.');
}
$alreadyReadKids[] = $reference->value;
$object = $this->parser->getIndirectObject($reference->value);
$type = PdfDictionary::get($object->value, 'Type');
@@ -168,6 +175,7 @@ class PdfReader
if ($type->value === 'Pages') {
$kids = PdfType::resolve(PdfDictionary::get($dict, 'Kids'), $this->parser);
try {
$alreadyReadKids[] = $page->objectNumber;
$page = $this->pages[$pageNumber - 1] = $readPages($kids);
} catch (PdfReaderException $e) {
if ($e->getCode() !== PdfReaderException::KIDS_EMPTY) {
@@ -202,7 +210,8 @@ class PdfReader
return;
}
$readPages = function ($kids, $count) use (&$readPages, $readAll) {
$alreadyReadKids = [];
$readPages = function ($kids, $count) use (&$readPages, &$alreadyReadKids, $readAll) {
$kids = PdfArray::ensure($kids);
$isLeaf = ($count->value === \count($kids->value));
@@ -214,6 +223,11 @@ class PdfReader
continue;
}
if (\in_array($reference->value, $alreadyReadKids, true)) {
throw new PdfReaderException('Recursive pages dictionary detected.');
}
$alreadyReadKids[] = $reference->value;
$object = $this->parser->getIndirectObject($reference->value);
$type = PdfDictionary::get($object->value, 'Type');