Gracefully handle errors loading plugin manifest

this isn't perfect, but it covers the common cases.
Now, the server won't spam crashdumps just because some plugin declared nested permissions.
This commit is contained in:
Dylan K. Taylor 2021-10-05 20:28:43 +01:00
parent 7245d15abe
commit e25c03eec1
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
5 changed files with 25 additions and 5 deletions

View File

@ -1746,6 +1746,12 @@ final class KnownTranslationFactory{
]);
}
public static function pocketmine_plugin_invalidManifest(Translatable|string $details) : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_PLUGIN_INVALIDMANIFEST, [
"details" => $details,
]);
}
public static function pocketmine_plugin_load(Translatable|string $param0) : Translatable{
return new Translatable(KnownTranslationKeys::POCKETMINE_PLUGIN_LOAD, [
0 => $param0,

View File

@ -364,6 +364,7 @@ final class KnownTranslationKeys{
public const POCKETMINE_PLUGIN_INCOMPATIBLEPHPVERSION = "pocketmine.plugin.incompatiblePhpVersion";
public const POCKETMINE_PLUGIN_INCOMPATIBLEPROTOCOL = "pocketmine.plugin.incompatibleProtocol";
public const POCKETMINE_PLUGIN_INVALIDAPI = "pocketmine.plugin.invalidAPI";
public const POCKETMINE_PLUGIN_INVALIDMANIFEST = "pocketmine.plugin.invalidManifest";
public const POCKETMINE_PLUGIN_LOAD = "pocketmine.plugin.load";
public const POCKETMINE_PLUGIN_LOADERROR = "pocketmine.plugin.loadError";
public const POCKETMINE_PLUGIN_RESTRICTEDNAME = "pocketmine.plugin.restrictedName";

View File

@ -25,6 +25,7 @@ namespace pocketmine\plugin;
use pocketmine\permission\Permission;
use pocketmine\permission\PermissionParser;
use pocketmine\permission\PermissionParserException;
use function array_map;
use function array_values;
use function is_array;
@ -99,20 +100,20 @@ class PluginDescription{
/**
* @param mixed[] $plugin
* @throws PluginException
* @throws PluginDescriptionParseException
*/
private function loadMap(array $plugin) : void{
$this->map = $plugin;
$this->name = $plugin["name"];
if(preg_match('/^[A-Za-z0-9 _.-]+$/', $this->name) === 0){
throw new PluginException("Invalid Plugin name");
throw new PluginDescriptionParseException("Invalid Plugin name");
}
$this->name = str_replace(" ", "_", $this->name);
$this->version = (string) $plugin["version"];
$this->main = $plugin["main"];
if(stripos($this->main, "pocketmine\\") === 0){
throw new PluginException("Invalid Plugin main, cannot start within the PocketMine namespace");
throw new PluginDescriptionParseException("Invalid Plugin main, cannot start within the PocketMine namespace");
}
$this->srcNamespacePrefix = $plugin["src-namespace-prefix"] ?? "";
@ -153,7 +154,7 @@ class PluginDescription{
if(isset($plugin["load"])){
$order = PluginEnableOrder::fromString($plugin["load"]);
if($order === null){
throw new PluginException("Invalid Plugin \"load\"");
throw new PluginDescriptionParseException("Invalid Plugin \"load\"");
}
$this->order = $order;
}else{
@ -175,7 +176,11 @@ class PluginDescription{
}
if(isset($plugin["permissions"])){
$this->permissions = PermissionParser::loadPermissions($plugin["permissions"]);
try{
$this->permissions = PermissionParser::loadPermissions($plugin["permissions"]);
}catch(PermissionParserException $e){
throw new PluginDescriptionParseException("Invalid Plugin \"permissions\": " . $e->getMessage(), 0, $e);
}
}
}

View File

@ -40,6 +40,7 @@ interface PluginLoader{
/**
* Gets the PluginDescription from the file
* @throws PluginDescriptionParseException
*/
public function getPluginDescription(string $file) : ?PluginDescription;

View File

@ -246,6 +246,13 @@ class PluginManager{
}
try{
$description = $loader->getPluginDescription($file);
}catch(PluginDescriptionParseException $e){
$this->server->getLogger()->error($this->server->getLanguage()->translate(KnownTranslationFactory::pocketmine_plugin_fileError(
$file,
$directory,
KnownTranslationFactory::pocketmine_plugin_invalidManifest($e->getMessage())
)));
continue;
}catch(\RuntimeException $e){ //TODO: more specific exception handling
$this->server->getLogger()->error($this->server->getLanguage()->translate(KnownTranslationFactory::pocketmine_plugin_fileError($file, $directory, $e->getMessage())));
$this->server->getLogger()->logException($e);