Merge branch '3.5'

This commit is contained in:
Dylan K. Taylor 2019-01-06 20:19:18 +00:00
commit 3ae722867c
3 changed files with 63 additions and 23 deletions

View File

@ -87,7 +87,11 @@ class CrashDump{
* having their content changed, version format changing, etc.
* It is not necessary to increase this when adding new fields.
*/
private const FORMAT_VERSION = 1;
private const FORMAT_VERSION = 2;
private const PLUGIN_INVOLVEMENT_NONE = "none";
private const PLUGIN_INVOLVEMENT_DIRECT = "direct";
private const PLUGIN_INVOLVEMENT_INDIRECT = "indirect";
/** @var Server */
private $server;
@ -207,7 +211,7 @@ class CrashDump{
$error = $lastExceptionError;
}else{
$error = (array) error_get_last();
$error["trace"] = Utils::printableCurrentTrace(3); //Skipping CrashDump->baseCrash, CrashDump->construct, Server->crashDump
$error["trace"] = Utils::currentTrace(3); //Skipping CrashDump->baseCrash, CrashDump->construct, Server->crashDump
$errorConversion = [
E_ERROR => "E_ERROR",
E_WARNING => "E_WARNING",
@ -245,24 +249,16 @@ class CrashDump{
$this->addLine("Line: " . $error["line"]);
$this->addLine("Type: " . $error["type"]);
if(strpos($error["file"], "src/pocketmine/") === false and strpos($error["file"], "vendor/pocketmine/") === false and file_exists($error["fullFile"])){
$this->addLine();
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
$this->data["plugin"] = true;
$reflection = new \ReflectionClass(PluginBase::class);
$file = $reflection->getProperty("file");
$file->setAccessible(true);
foreach($this->server->getPluginManager()->getPlugins() as $plugin){
$filePath = Utils::cleanPath($file->getValue($plugin));
if(strpos($error["file"], $filePath) === 0){
$this->data["plugin"] = $plugin->getName();
$this->addLine("BAD PLUGIN: " . $plugin->getDescription()->getFullName());
$this->data["plugin_involvement"] = self::PLUGIN_INVOLVEMENT_NONE;
if(!$this->determinePluginFromFile($error["fullFile"], true)){ //fatal errors won't leave any stack trace
foreach($error["trace"] as $frame){
if(!isset($frame["file"])){
continue; //PHP core
}
if($this->determinePluginFromFile($frame["file"], false)){
break;
}
}
}else{
$this->data["plugin"] = false;
}
$this->addLine();
@ -279,12 +275,40 @@ class CrashDump{
$this->addLine();
$this->addLine("Backtrace:");
foreach(($this->data["trace"] = $error["trace"]) as $line){
foreach(($this->data["trace"] = Utils::printableTrace($error["trace"])) as $line){
$this->addLine($line);
}
$this->addLine();
}
private function determinePluginFromFile(string $filePath, bool $crashFrame) : bool{
$frameCleanPath = Utils::cleanPath($filePath); //this will be empty in phar stub
if($frameCleanPath !== "" and strpos($frameCleanPath, "src/pocketmine/") === false and strpos($frameCleanPath, "vendor/pocketmine/") === false and file_exists($filePath)){
$this->addLine();
if($crashFrame){
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
$this->data["plugin_involvement"] = self::PLUGIN_INVOLVEMENT_DIRECT;
}else{
$this->addLine("A PLUGIN WAS INVOLVED IN THIS CRASH");
$this->data["plugin_involvement"] = self::PLUGIN_INVOLVEMENT_INDIRECT;
}
$reflection = new \ReflectionClass(PluginBase::class);
$file = $reflection->getProperty("file");
$file->setAccessible(true);
foreach($this->server->getPluginManager()->getPlugins() as $plugin){
$filePath = Utils::cleanPath($file->getValue($plugin));
if(strpos($frameCleanPath, $filePath) === 0){
$this->data["plugin"] = $plugin->getName();
$this->addLine("BAD PLUGIN: " . $plugin->getDescription()->getFullName());
break;
}
}
return true;
}
return false;
}
private function generalData(){
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
$this->data["general"] = [];

View File

@ -104,7 +104,6 @@ use pocketmine\tile\Tile;
use pocketmine\timings\Timings;
use pocketmine\timings\TimingsHandler;
use pocketmine\updater\AutoUpdater;
use pocketmine\utils\Binary;
use pocketmine\utils\Config;
use pocketmine\utils\Internet;
use pocketmine\utils\MainLogger;
@ -151,6 +150,7 @@ use function pcntl_signal;
use function pcntl_signal_dispatch;
use function preg_replace;
use function random_bytes;
use function random_int;
use function realpath;
use function register_shutdown_function;
use function rename;
@ -169,6 +169,8 @@ use function time;
use function touch;
use function trim;
use const DIRECTORY_SEPARATOR;
use const INT32_MAX;
use const INT32_MIN;
use const PHP_EOL;
use const PHP_INT_MAX;
use const PTHREADS_INHERIT_NONE;
@ -1120,7 +1122,7 @@ class Server{
return false;
}
$seed = $seed ?? Binary::readInt(random_bytes(4));
$seed = $seed ?? random_int(INT32_MIN, INT32_MAX);
if(!isset($options["preset"])){
$options["preset"] = $this->getConfigString("generator-settings", "");
@ -2273,7 +2275,7 @@ class Server{
"fullFile" => $e->getFile(),
"file" => $errfile,
"line" => $errline,
"trace" => Utils::printableTrace($trace)
"trace" => $trace
];
global $lastExceptionError, $lastError;
@ -2312,7 +2314,7 @@ class Server{
if(is_string($plugin)){
$p = $this->pluginManager->getPlugin($plugin);
if($p instanceof Plugin and !($p->getPluginLoader() instanceof PharPluginLoader)){
$report = false;
$this->logger->debug("Not sending crashdump due to caused by non-phar plugin");
}
}

View File

@ -578,7 +578,21 @@ class Utils{
}
public static function cleanPath($path){
return str_replace(["\\", ".php", "phar://", str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PATH), str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PLUGIN_PATH)], ["/", "", "", "", ""], $path);
$result = str_replace(["\\", ".php", "phar://"], ["/", "", ""], $path);
//remove relative paths
//TODO: make these paths dynamic so they can be unit-tested against
static $cleanPaths = [
\pocketmine\PLUGIN_PATH => "plugins", //this has to come BEFORE \pocketmine\PATH because it's inside that by default on src installations
\pocketmine\PATH => ""
];
foreach($cleanPaths as $cleanPath => $replacement){
$cleanPath = rtrim(str_replace(["\\", "phar://"], ["/", ""], $cleanPath), "/");
if(strpos($result, $cleanPath) === 0){
$result = ltrim(str_replace($cleanPath, $replacement, $result), "/");
}
}
return $result;
}
/**