From d2fb32c28ae0b0835c587e53520290c3f8c4cdc9 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 21 Mar 2018 10:40:08 +0000 Subject: [PATCH] PluginManager: added event call recursion limit, closes #2109 This prevents unexplained segfaults on accidental event call recursion by limiting the max depth of event call stack to 50. If another event attempts to be called, an exception will be thrown. --- src/pocketmine/plugin/PluginManager.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/pocketmine/plugin/PluginManager.php b/src/pocketmine/plugin/PluginManager.php index 7e1a8ad3d..56c2ad1fd 100644 --- a/src/pocketmine/plugin/PluginManager.php +++ b/src/pocketmine/plugin/PluginManager.php @@ -40,6 +40,7 @@ use pocketmine\timings\TimingsHandler; * Manages all the plugins, Permissions and Permissibles */ class PluginManager{ + private const MAX_EVENT_CALL_DEPTH = 50; /** @var Server */ private $server; @@ -87,6 +88,9 @@ class PluginManager{ */ protected $fileAssociations = []; + /** @var int */ + private $eventCallDepth = 0; + /** @var TimingsHandler */ public static $pluginParentTimer; @@ -671,9 +675,15 @@ class PluginManager{ * @param Event $event */ public function callEvent(Event $event){ + if($this->eventCallDepth >= self::MAX_EVENT_CALL_DEPTH){ + //this exception will be caught by the parent event call if all else fails + throw new \RuntimeException("Recursive event call detected (reached max depth of " . self::MAX_EVENT_CALL_DEPTH . " calls)"); + } + $handlerList = HandlerList::getHandlerListFor(get_class($event)); assert($handlerList !== null, "Called event should have a valid HandlerList"); + ++$this->eventCallDepth; foreach(EventPriority::ALL as $priority){ $currentList = $handlerList; while($currentList !== null){ @@ -699,6 +709,7 @@ class PluginManager{ $currentList = $currentList->getParent(); } } + --$this->eventCallDepth; } /**