1
0
mirror of https://github.com/erusev/parsedown.git synced 2023-08-10 21:13:06 +03:00

Limit recursion depth by configurable

Fixes https://github.com/erusev/parsedown/issues/681
This commit is contained in:
Aidan Woods
2019-04-07 17:34:40 +01:00
parent b9b75dbcea
commit 9eb6a02334
3 changed files with 122 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
<?php
namespace Erusev\Parsedown\Configurables;
use Erusev\Parsedown\Configurable;
final class RecursionLimiter implements Configurable
{
/** @var int */
private $maxDepth;
/** @var int */
private $currentDepth;
/**
* @param int $maxDepth
* @param int $currentDepth
*/
private function __construct($maxDepth, $currentDepth)
{
$this->maxDepth = $maxDepth;
$this->currentDepth = $currentDepth;
}
/** @return self */
public static function initial()
{
return self::maxDepth(256);
}
/**
* @param int $maxDepth
* @return self
*/
public static function maxDepth($maxDepth)
{
return new self($maxDepth, 0);
}
/** @return self */
public function increment()
{
return new self($this->maxDepth, $this->currentDepth + 1);
}
/** @return bool */
public function isDepthExceeded()
{
return ($this->maxDepth < $this->currentDepth);
}
}

View File

@@ -13,6 +13,7 @@ use Erusev\Parsedown\Components\Inlines\PlainText;
use Erusev\Parsedown\Components\StateUpdatingBlock;
use Erusev\Parsedown\Configurables\BlockTypes;
use Erusev\Parsedown\Configurables\InlineTypes;
use Erusev\Parsedown\Configurables\RecursionLimiter;
use Erusev\Parsedown\Html\Renderable;
use Erusev\Parsedown\Html\Renderables\Text;
use Erusev\Parsedown\Parsing\Excerpt;
@@ -82,6 +83,14 @@ final class Parsedown
*/
public static function blocks(Lines $Lines, State $State)
{
$RecursionLimiter = $State->get(RecursionLimiter::class)->increment();
if ($RecursionLimiter->isDepthExceeded()) {
$State = $State->setting(new BlockTypes([], []));
}
$State = $State->setting($RecursionLimiter);
/** @var Block[] */
$Blocks = [];
/** @var Block|null */
@@ -180,6 +189,14 @@ final class Parsedown
# standardize line breaks
$text = \str_replace(["\r\n", "\r"], "\n", $text);
$RecursionLimiter = $State->get(RecursionLimiter::class)->increment();
if ($RecursionLimiter->isDepthExceeded()) {
return [Plaintext::build(new Excerpt($text, 0), $State)];
}
$State = $State->setting($RecursionLimiter);
/** @var Inline[] */
$Inlines = [];