mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-30 06:59:01 +01:00
Ban plugins from using file_get_contents, PDO, files
This commit is contained in:
parent
e4ff361ee7
commit
1f654d8f26
@ -58,7 +58,8 @@
|
|||||||
"psr/http-factory": "^1.0",
|
"psr/http-factory": "^1.0",
|
||||||
"psr/log": "^3",
|
"psr/log": "^3",
|
||||||
"webmozart/assert": "^1.11",
|
"webmozart/assert": "^1.11",
|
||||||
"bacon/bacon-qr-code": "^2.0"
|
"bacon/bacon-qr-code": "^2.0",
|
||||||
|
"nikic/php-parser": "^4.16"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpdocumentor/reflection-docblock": "dev-master",
|
"phpdocumentor/reflection-docblock": "dev-master",
|
||||||
|
@ -31,6 +31,17 @@ use danog\MadelineProto\EventHandler\Filter\Filter;
|
|||||||
use danog\MadelineProto\EventHandler\Handler;
|
use danog\MadelineProto\EventHandler\Handler;
|
||||||
use danog\MadelineProto\EventHandler\Update;
|
use danog\MadelineProto\EventHandler\Update;
|
||||||
use Generator;
|
use Generator;
|
||||||
|
use mysqli;
|
||||||
|
use PDO;
|
||||||
|
use PhpParser\Node;
|
||||||
|
use PhpParser\Node\Expr;
|
||||||
|
use PhpParser\Node\Expr\FuncCall;
|
||||||
|
use PhpParser\Node\Expr\New_;
|
||||||
|
use PhpParser\Node\Name;
|
||||||
|
use PhpParser\NodeFinder;
|
||||||
|
use PhpParser\NodeVisitor\NameResolver;
|
||||||
|
use PhpParser\ParserFactory;
|
||||||
|
use PHPStan\PhpDocParser\Ast\NodeTraverser;
|
||||||
use ReflectionAttribute;
|
use ReflectionAttribute;
|
||||||
use ReflectionClass;
|
use ReflectionClass;
|
||||||
use ReflectionMethod;
|
use ReflectionMethod;
|
||||||
@ -40,6 +51,7 @@ use Webmozart\Assert\Assert;
|
|||||||
use function Amp\File\isDirectory;
|
use function Amp\File\isDirectory;
|
||||||
use function Amp\File\isFile;
|
use function Amp\File\isFile;
|
||||||
use function Amp\File\listFiles;
|
use function Amp\File\listFiles;
|
||||||
|
use function Amp\File\read;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler.
|
* Event handler.
|
||||||
@ -302,8 +314,47 @@ abstract class EventHandler extends AbstractAPI
|
|||||||
Assert::true(\is_subclass_of($plugin, PluginEventHandler::class), "$plugin must extend ".PluginEventHandler::class);
|
Assert::true(\is_subclass_of($plugin, PluginEventHandler::class), "$plugin must extend ".PluginEventHandler::class);
|
||||||
Assert::notEq($plugin, PluginEventHandler::class);
|
Assert::notEq($plugin, PluginEventHandler::class);
|
||||||
Assert::true(\str_contains(\ltrim($plugin, '\\'), '\\'), "$plugin must be in a namespace!");
|
Assert::true(\str_contains(\ltrim($plugin, '\\'), '\\'), "$plugin must be in a namespace!");
|
||||||
|
self::validatePlugin($plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $plugins;
|
return $plugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const BANNED_FUNCTIONS = [
|
||||||
|
'file_get_contents',
|
||||||
|
'file_put_contents',
|
||||||
|
'curl_exec',
|
||||||
|
'mysqli_connect',
|
||||||
|
'fopen',
|
||||||
|
'fsockopen'
|
||||||
|
];
|
||||||
|
private const BANNED_CLASSES = [
|
||||||
|
PDO::class,
|
||||||
|
mysqli::class,
|
||||||
|
];
|
||||||
|
private static function validatePlugin(string $class): void {
|
||||||
|
$file = read((new ReflectionClass($class))->getFileName());
|
||||||
|
$file = (new ParserFactory)->create(ParserFactory::ONLY_PHP7)->parse($file);
|
||||||
|
Assert::notNull($file);
|
||||||
|
$traverser = new NodeTraverser([new NameResolver()]);
|
||||||
|
$file = $traverser->traverse($file);
|
||||||
|
|
||||||
|
/** @var FuncCall $call */
|
||||||
|
foreach ((new NodeFinder)->findInstanceOf($file, FuncCall::class) as $call) {
|
||||||
|
if ($call->name instanceof Name
|
||||||
|
&& in_array($name = $call->name->toLowerString(), self::BANNED_FUNCTIONS, true)
|
||||||
|
) {
|
||||||
|
throw new AssertionError("An error occurred while analyzing plugin $class: plugins may not use the non-async blocking function $name!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var New_ $call */
|
||||||
|
foreach ((new NodeFinder)->findInstanceOf($file, New_::class) as $new) {
|
||||||
|
if ($new->class instanceof Name
|
||||||
|
&& in_array($name = $new->class->toLowerString(), self::BANNED_CLASSES, true)
|
||||||
|
) {
|
||||||
|
throw new AssertionError("An error occurred while analyzing plugin $class: plugins may not use the non-async blocking class $name!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
|
use Amp\ByteStream\ReadableBuffer;
|
||||||
use ArrayAccess;
|
use ArrayAccess;
|
||||||
use Closure;
|
use Closure;
|
||||||
use Countable;
|
use Countable;
|
||||||
@ -100,6 +101,12 @@ abstract class Tools extends AsyncTools
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Converts a string into an async amphp stream.
|
||||||
|
*/
|
||||||
|
public static function stringToStream(string $str): ReadableBuffer {
|
||||||
|
return new ReadableBuffer($str);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Sanify TL obtained from JSON for TL serialization.
|
* Sanify TL obtained from JSON for TL serialization.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user