MDL-86353 mod_assign: Sync exception handling in PdfType and PdfReader
This commit is contained in:
@@ -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');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user