From 889d048ca39d794c38a3e7220e709776ec5b64f2 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 8 Dec 2021 19:33:45 +0000 Subject: [PATCH] Make use of Utils::assumeNotFalse() in a bunch of places I've stuck to only doing this in the places where I'm sure we should never get false back. Other places I'm less sure of (and I found more bugs along the way). --- build/make-release.php | 2 +- src/MemoryManager.php | 6 +- src/PocketMine.php | 9 +- src/Server.php | 7 +- src/command/defaults/TimingsCommand.php | 3 +- src/console/ConsoleReader.php | 6 +- src/console/ConsoleReaderThread.php | 12 ++- .../CraftingManagerFromDataHelper.php | 3 +- src/crash/CrashDump.php | 4 +- .../LegacyToStringBidirectionalIdMap.php | 3 +- src/item/LegacyStringToItemParser.php | 4 +- src/lang/Language.php | 3 +- src/network/mcpe/JwtUtils.php | 7 +- .../mcpe/compression/ZlibCompressor.php | 6 +- .../mcpe/convert/GlobalItemTypeDictionary.php | 4 +- src/network/mcpe/convert/ItemTranslator.php | 3 +- .../mcpe/convert/RuntimeBlockMapping.php | 18 ++-- .../mcpe/encryption/EncryptionUtils.php | 3 +- src/network/upnp/UPnP.php | 20 ++--- src/permission/BanEntry.php | 5 +- src/plugin/PluginManager.php | 3 +- src/resourcepacks/ZippedResourcePack.php | 5 +- src/utils/Filesystem.php | 8 +- src/utils/Timezone.php | 2 +- src/world/format/io/data/JavaWorldData.php | 7 +- tests/phpstan/configs/actual-problems.neon | 85 ------------------- 26 files changed, 67 insertions(+), 171 deletions(-) diff --git a/build/make-release.php b/build/make-release.php index e3a3dad81..c33364481 100644 --- a/build/make-release.php +++ b/build/make-release.php @@ -50,7 +50,7 @@ use const STR_PAD_LEFT; require_once dirname(__DIR__) . '/vendor/autoload.php'; function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev, string $channel) : void{ - $versionInfo = file_get_contents($versionInfoPath); + $versionInfo = Utils::assumeNotFalse(file_get_contents($versionInfoPath), $versionInfoPath . " should always exist"); $versionInfo = preg_replace( $pattern = '/^([\t ]*public )?const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m', '$1const BASE_VERSION = "' . $newVersion . '";', diff --git a/src/MemoryManager.php b/src/MemoryManager.php index 3bf0f5455..beffbf7e2 100644 --- a/src/MemoryManager.php +++ b/src/MemoryManager.php @@ -28,7 +28,6 @@ use pocketmine\network\mcpe\cache\ChunkCache; use pocketmine\scheduler\DumpWorkerMemoryTask; use pocketmine\scheduler\GarbageCollectionTask; use pocketmine\timings\Timings; -use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\Process; use pocketmine\utils\Utils; use Webmozart\PathUtil\Path; @@ -292,8 +291,7 @@ class MemoryManager{ * @param mixed $startingObject */ public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger) : void{ - $hardLimit = ini_get('memory_limit'); - if($hardLimit === false) throw new AssumptionFailedError("memory_limit INI directive should always exist"); + $hardLimit = Utils::assumeNotFalse(ini_get('memory_limit'), "memory_limit INI directive should always exist"); ini_set('memory_limit', '-1'); gc_disable(); @@ -301,7 +299,7 @@ class MemoryManager{ mkdir($outputFolder, 0777, true); } - $obData = fopen(Path::join($outputFolder, "objects.js"), "wb+"); + $obData = Utils::assumeNotFalse(fopen(Path::join($outputFolder, "objects.js"), "wb+")); $objects = []; diff --git a/src/PocketMine.php b/src/PocketMine.php index a587a7704..0ff3b5c64 100644 --- a/src/PocketMine.php +++ b/src/PocketMine.php @@ -32,14 +32,16 @@ namespace pocketmine { use pocketmine\utils\ServerKiller; use pocketmine\utils\Terminal; use pocketmine\utils\Timezone; + use pocketmine\utils\Utils; use pocketmine\wizard\SetupWizard; use Webmozart\PathUtil\Path; use function defined; use function extension_loaded; + use function getcwd; use function phpversion; use function preg_match; use function preg_quote; - use function strpos; + use function realpath; use function version_compare; require_once __DIR__ . '/VersionInfo.php'; @@ -249,8 +251,9 @@ JIT_WARNING $opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]); - $dataPath = isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR; - $pluginPath = isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR; + $cwd = Utils::assumeNotFalse(realpath(Utils::assumeNotFalse(getcwd()))); + $dataPath = isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : $cwd . DIRECTORY_SEPARATOR; + $pluginPath = isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : $cwd . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR; Filesystem::addCleanedPath($pluginPath, Filesystem::CLEAN_PATH_PLUGINS_PREFIX); if(!file_exists($dataPath)){ diff --git a/src/Server.php b/src/Server.php index 90d96d047..fc0be90af 100644 --- a/src/Server.php +++ b/src/Server.php @@ -537,10 +537,7 @@ class Server{ if(!$ev->isCancelled()){ Timings::$syncPlayerDataSave->time(function() use ($name, $ev) : void{ $nbt = new BigEndianNbtSerializer(); - $contents = zlib_encode($nbt->write(new TreeRoot($ev->getSaveData())), ZLIB_ENCODING_GZIP); - if($contents === false){ - throw new AssumptionFailedError("zlib_encode() failed unexpectedly"); - } + $contents = Utils::assumeNotFalse(zlib_encode($nbt->write(new TreeRoot($ev->getSaveData())), ZLIB_ENCODING_GZIP), "zlib_encode() failed unexpectedly"); try{ Filesystem::safeFilePutContents($this->getPlayerDataPath($name), $contents); }catch(\RuntimeException | \ErrorException $e){ @@ -791,7 +788,7 @@ class Server{ $this->logger->info("Loading server configuration"); $pocketmineYmlPath = Path::join($this->dataPath, "pocketmine.yml"); if(!file_exists($pocketmineYmlPath)){ - $content = file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, "pocketmine.yml")); + $content = Utils::assumeNotFalse(file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, "pocketmine.yml")), "Missing required resource file"); if(VersionInfo::IS_DEVELOPMENT_BUILD){ $content = str_replace("preferred-channel: stable", "preferred-channel: beta", $content); } diff --git a/src/command/defaults/TimingsCommand.php b/src/command/defaults/TimingsCommand.php index 26839b312..c894bb94f 100644 --- a/src/command/defaults/TimingsCommand.php +++ b/src/command/defaults/TimingsCommand.php @@ -34,6 +34,7 @@ use pocketmine\scheduler\BulkCurlTaskOperation; use pocketmine\timings\TimingsHandler; use pocketmine\utils\InternetException; use pocketmine\utils\InternetRequestResult; +use pocketmine\utils\Utils; use Webmozart\PathUtil\Path; use function count; use function fclose; @@ -105,7 +106,7 @@ class TimingsCommand extends VanillaCommand{ }elseif($mode === "merged" or $mode === "report" or $paste){ $timings = ""; if($paste){ - $fileTimings = fopen("php://temp", "r+b"); + $fileTimings = Utils::assumeNotFalse(fopen("php://temp", "r+b"), "Opening php://temp should never fail"); }else{ $index = 0; $timingFolder = Path::join($sender->getServer()->getDataPath(), "timings"); diff --git a/src/console/ConsoleReader.php b/src/console/ConsoleReader.php index 77a3f4b6f..ac7b6f644 100644 --- a/src/console/ConsoleReader.php +++ b/src/console/ConsoleReader.php @@ -23,7 +23,7 @@ declare(strict_types=1); namespace pocketmine\console; -use pocketmine\utils\AssumptionFailedError; +use pocketmine\utils\Utils; use function fclose; use function fgets; use function fopen; @@ -45,9 +45,7 @@ final class ConsoleReader{ fclose($this->stdin); } - $stdin = fopen("php://stdin", "r"); - if($stdin === false) throw new AssumptionFailedError("Opening stdin should never fail"); - $this->stdin = $stdin; + $this->stdin = Utils::assumeNotFalse(fopen("php://stdin", "r"), "Opening stdin should never fail"); } /** diff --git a/src/console/ConsoleReaderThread.php b/src/console/ConsoleReaderThread.php index bdfccd80f..519d01121 100644 --- a/src/console/ConsoleReaderThread.php +++ b/src/console/ConsoleReaderThread.php @@ -26,6 +26,7 @@ namespace pocketmine\console; use pocketmine\snooze\SleeperNotifier; use pocketmine\thread\Thread; use pocketmine\utils\AssumptionFailedError; +use pocketmine\utils\Utils; use Webmozart\PathUtil\Path; use function base64_encode; use function fgets; @@ -81,21 +82,18 @@ final class ConsoleReaderThread extends Thread{ if($server === false){ throw new \RuntimeException("Failed to open console reader socket server"); } - $address = stream_socket_get_name($server, false); - if($address === false) throw new AssumptionFailedError("stream_socket_get_name() shouldn't return false here"); + $address = Utils::assumeNotFalse(stream_socket_get_name($server, false), "stream_socket_get_name() shouldn't return false here"); //Windows sucks, and likes to corrupt UTF-8 file paths when they travel to the subprocess, so we base64 encode //the path to avoid the problem. This is an abysmally shitty hack, but here we are :( - $sub = proc_open( + $sub = Utils::assumeNotFalse(proc_open( [PHP_BINARY, '-r', sprintf('require base64_decode("%s", true);', base64_encode(Path::join(__DIR__, 'ConsoleReaderChildProcess.php'))), $address], [ 2 => fopen("php://stderr", "w"), ], $pipes - ); - if($sub === false){ - throw new AssumptionFailedError("Something has gone horribly wrong"); - } + ), "Something has gone horribly wrong"); + $client = stream_socket_accept($server, 15); if($client === false){ throw new AssumptionFailedError("stream_socket_accept() returned false"); diff --git a/src/crafting/CraftingManagerFromDataHelper.php b/src/crafting/CraftingManagerFromDataHelper.php index 6660bb602..bd8465b1b 100644 --- a/src/crafting/CraftingManagerFromDataHelper.php +++ b/src/crafting/CraftingManagerFromDataHelper.php @@ -25,6 +25,7 @@ namespace pocketmine\crafting; use pocketmine\item\Item; use pocketmine\utils\AssumptionFailedError; +use pocketmine\utils\Utils; use function array_map; use function file_get_contents; use function is_array; @@ -33,7 +34,7 @@ use function json_decode; final class CraftingManagerFromDataHelper{ public static function make(string $filePath) : CraftingManager{ - $recipes = json_decode(file_get_contents($filePath), true); + $recipes = json_decode(Utils::assumeNotFalse(file_get_contents($filePath), "Missing required resource file"), true); if(!is_array($recipes)){ throw new AssumptionFailedError("recipes.json root should contain a map of recipe types"); } diff --git a/src/crash/CrashDump.php b/src/crash/CrashDump.php index f72c05fec..c265aad57 100644 --- a/src/crash/CrashDump.php +++ b/src/crash/CrashDump.php @@ -105,9 +105,7 @@ class CrashDump{ $this->extraData(); $json = json_encode($this->data, JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR); - $zlibEncoded = zlib_encode($json, ZLIB_ENCODING_DEFLATE, 9); - if($zlibEncoded === false) throw new AssumptionFailedError("ZLIB compression failed"); - $this->encodedData = $zlibEncoded; + $this->encodedData = Utils::assumeNotFalse(zlib_encode($json, ZLIB_ENCODING_DEFLATE, 9), "ZLIB compression failed"); } public function getEncodedData() : string{ diff --git a/src/data/bedrock/LegacyToStringBidirectionalIdMap.php b/src/data/bedrock/LegacyToStringBidirectionalIdMap.php index 0dcc7ff0f..a7ce83b1f 100644 --- a/src/data/bedrock/LegacyToStringBidirectionalIdMap.php +++ b/src/data/bedrock/LegacyToStringBidirectionalIdMap.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace pocketmine\data\bedrock; use pocketmine\utils\AssumptionFailedError; +use pocketmine\utils\Utils; use function file_get_contents; use function is_array; use function is_int; @@ -44,7 +45,7 @@ abstract class LegacyToStringBidirectionalIdMap{ private $stringToLegacy = []; public function __construct(string $file){ - $stringToLegacyId = json_decode(file_get_contents($file), true); + $stringToLegacyId = json_decode(Utils::assumeNotFalse(file_get_contents($file), "Missing required resource file"), true); if(!is_array($stringToLegacyId)){ throw new AssumptionFailedError("Invalid format of ID map"); } diff --git a/src/item/LegacyStringToItemParser.php b/src/item/LegacyStringToItemParser.php index ccc824b0d..3065cb1bd 100644 --- a/src/item/LegacyStringToItemParser.php +++ b/src/item/LegacyStringToItemParser.php @@ -25,6 +25,7 @@ namespace pocketmine\item; use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\SingletonTrait; +use pocketmine\utils\Utils; use Webmozart\PathUtil\Path; use function explode; use function file_get_contents; @@ -55,8 +56,7 @@ final class LegacyStringToItemParser{ private static function make() : self{ $result = new self(ItemFactory::getInstance()); - $mappingsRaw = @file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, 'item_from_string_bc_map.json')); - if($mappingsRaw === false) throw new AssumptionFailedError("Missing required resource file"); + $mappingsRaw = Utils::assumeNotFalse(@file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, 'item_from_string_bc_map.json')), "Missing required resource file"); $mappings = json_decode($mappingsRaw, true); if(!is_array($mappings)) throw new AssumptionFailedError("Invalid mappings format, expected array"); diff --git a/src/lang/Language.php b/src/lang/Language.php index 33ad93888..f86b1bba5 100644 --- a/src/lang/Language.php +++ b/src/lang/Language.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace pocketmine\lang; +use pocketmine\utils\Utils; use Webmozart\PathUtil\Path; use function array_filter; use function array_map; @@ -123,7 +124,7 @@ class Language{ protected static function loadLang(string $path, string $languageCode) : array{ $file = Path::join($path, $languageCode . ".ini"); if(file_exists($file)){ - return array_map('\stripcslashes', parse_ini_file($file, false, INI_SCANNER_RAW)); + return array_map('\stripcslashes', Utils::assumeNotFalse(parse_ini_file($file, false, INI_SCANNER_RAW), "Missing or inaccessible required resource files")); } throw new LanguageNotFoundException("Language \"$languageCode\" not found"); diff --git a/src/network/mcpe/JwtUtils.php b/src/network/mcpe/JwtUtils.php index 06d5cdfee..7a0a706c8 100644 --- a/src/network/mcpe/JwtUtils.php +++ b/src/network/mcpe/JwtUtils.php @@ -27,6 +27,7 @@ use FG\ASN1\Exception\ParserException; use FG\ASN1\Universal\Integer; use FG\ASN1\Universal\Sequence; use pocketmine\utils\AssumptionFailedError; +use pocketmine\utils\Utils; use function base64_decode; use function base64_encode; use function count; @@ -185,11 +186,7 @@ final class JwtUtils{ } public static function emitDerPublicKey(\OpenSSLAsymmetricKey $opensslKey) : string{ - $details = openssl_pkey_get_details($opensslKey); - if($details === false){ - throw new AssumptionFailedError("Failed to get details from OpenSSL key resource"); - } - + $details = Utils::assumeNotFalse(openssl_pkey_get_details($opensslKey), "Failed to get details from OpenSSL key resource"); /** @var string $pemKey */ $pemKey = $details['key']; if(preg_match("@^-----BEGIN[A-Z\d ]+PUBLIC KEY-----\n([A-Za-z\d+/\n]+)\n-----END[A-Z\d ]+PUBLIC KEY-----\n$@", $pemKey, $matches) === 1){ diff --git a/src/network/mcpe/compression/ZlibCompressor.php b/src/network/mcpe/compression/ZlibCompressor.php index b5bd33bcb..284a8dcb7 100644 --- a/src/network/mcpe/compression/ZlibCompressor.php +++ b/src/network/mcpe/compression/ZlibCompressor.php @@ -23,8 +23,8 @@ declare(strict_types=1); namespace pocketmine\network\mcpe\compression; -use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\SingletonTrait; +use pocketmine\utils\Utils; use function function_exists; use function libdeflate_deflate_compress; use function strlen; @@ -75,9 +75,7 @@ final class ZlibCompressor implements Compressor{ } private static function zlib_encode(string $data, int $level) : string{ - $result = zlib_encode($data, ZLIB_ENCODING_RAW, $level); - if($result === false) throw new AssumptionFailedError("ZLIB compression failed"); - return $result; + return Utils::assumeNotFalse(zlib_encode($data, ZLIB_ENCODING_RAW, $level), "ZLIB compression failed"); } public function compress(string $payload) : string{ diff --git a/src/network/mcpe/convert/GlobalItemTypeDictionary.php b/src/network/mcpe/convert/GlobalItemTypeDictionary.php index d3ab00f53..61510e590 100644 --- a/src/network/mcpe/convert/GlobalItemTypeDictionary.php +++ b/src/network/mcpe/convert/GlobalItemTypeDictionary.php @@ -27,6 +27,7 @@ use pocketmine\network\mcpe\protocol\serializer\ItemTypeDictionary; use pocketmine\network\mcpe\protocol\types\ItemTypeEntry; use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\SingletonTrait; +use pocketmine\utils\Utils; use Webmozart\PathUtil\Path; use function file_get_contents; use function is_array; @@ -39,8 +40,7 @@ final class GlobalItemTypeDictionary{ use SingletonTrait; private static function make() : self{ - $data = file_get_contents(Path::join(\pocketmine\BEDROCK_DATA_PATH, 'required_item_list.json')); - if($data === false) throw new AssumptionFailedError("Missing required resource file"); + $data = Utils::assumeNotFalse(file_get_contents(Path::join(\pocketmine\BEDROCK_DATA_PATH, 'required_item_list.json')), "Missing required resource file"); $table = json_decode($data, true); if(!is_array($table)){ throw new AssumptionFailedError("Invalid item list format"); diff --git a/src/network/mcpe/convert/ItemTranslator.php b/src/network/mcpe/convert/ItemTranslator.php index 4aa82f32b..87e1a6ae6 100644 --- a/src/network/mcpe/convert/ItemTranslator.php +++ b/src/network/mcpe/convert/ItemTranslator.php @@ -67,8 +67,7 @@ final class ItemTranslator{ private $complexNetToCoreMapping = []; private static function make() : self{ - $data = file_get_contents(Path::join(\pocketmine\BEDROCK_DATA_PATH, 'r16_to_current_item_map.json')); - if($data === false) throw new AssumptionFailedError("Missing required resource file"); + $data = Utils::assumeNotFalse(file_get_contents(Path::join(\pocketmine\BEDROCK_DATA_PATH, 'r16_to_current_item_map.json')), "Missing required resource file"); $json = json_decode($data, true); if(!is_array($json) or !isset($json["simple"], $json["complex"]) || !is_array($json["simple"]) || !is_array($json["complex"])){ throw new AssumptionFailedError("Invalid item table format"); diff --git a/src/network/mcpe/convert/RuntimeBlockMapping.php b/src/network/mcpe/convert/RuntimeBlockMapping.php index dfa69168e..75835be0f 100644 --- a/src/network/mcpe/convert/RuntimeBlockMapping.php +++ b/src/network/mcpe/convert/RuntimeBlockMapping.php @@ -30,8 +30,8 @@ use pocketmine\nbt\tag\CompoundTag; use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer; use pocketmine\network\mcpe\protocol\serializer\PacketSerializer; use pocketmine\network\mcpe\protocol\serializer\PacketSerializerContext; -use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\SingletonTrait; +use pocketmine\utils\Utils; use Webmozart\PathUtil\Path; use function file_get_contents; @@ -49,11 +49,11 @@ final class RuntimeBlockMapping{ private $bedrockKnownStates; private function __construct(){ - $canonicalBlockStatesFile = file_get_contents(Path::join(\pocketmine\BEDROCK_DATA_PATH, "canonical_block_states.nbt")); - if($canonicalBlockStatesFile === false){ - throw new AssumptionFailedError("Missing required resource file"); - } - $stream = PacketSerializer::decoder($canonicalBlockStatesFile, 0, new PacketSerializerContext(GlobalItemTypeDictionary::getInstance()->getDictionary())); + $stream = PacketSerializer::decoder( + Utils::assumeNotFalse(file_get_contents(Path::join(\pocketmine\BEDROCK_DATA_PATH, "canonical_block_states.nbt")), "Missing required resource file"), + 0, + new PacketSerializerContext(GlobalItemTypeDictionary::getInstance()->getDictionary()) + ); $list = []; while(!$stream->feof()){ $list[] = $stream->getNbtCompoundRoot(); @@ -67,7 +67,11 @@ final class RuntimeBlockMapping{ $legacyIdMap = LegacyBlockIdToStringIdMap::getInstance(); /** @var R12ToCurrentBlockMapEntry[] $legacyStateMap */ $legacyStateMap = []; - $legacyStateMapReader = PacketSerializer::decoder(file_get_contents(Path::join(\pocketmine\BEDROCK_DATA_PATH, "r12_to_current_block_map.bin")), 0, new PacketSerializerContext(GlobalItemTypeDictionary::getInstance()->getDictionary())); + $legacyStateMapReader = PacketSerializer::decoder( + Utils::assumeNotFalse(file_get_contents(Path::join(\pocketmine\BEDROCK_DATA_PATH, "r12_to_current_block_map.bin")), "Missing required resource file"), + 0, + new PacketSerializerContext(GlobalItemTypeDictionary::getInstance()->getDictionary()) + ); $nbtReader = new NetworkNbtSerializer(); while(!$legacyStateMapReader->feof()){ $id = $legacyStateMapReader->getString(); diff --git a/src/network/mcpe/encryption/EncryptionUtils.php b/src/network/mcpe/encryption/EncryptionUtils.php index 0ad2ebfee..0aec6b445 100644 --- a/src/network/mcpe/encryption/EncryptionUtils.php +++ b/src/network/mcpe/encryption/EncryptionUtils.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace pocketmine\network\mcpe\encryption; use pocketmine\network\mcpe\JwtUtils; +use pocketmine\utils\Utils; use function base64_encode; use function bin2hex; use function gmp_init; @@ -49,7 +50,7 @@ final class EncryptionUtils{ } public static function generateKey(\GMP $secret, string $salt) : string{ - return openssl_digest($salt . hex2bin(str_pad(gmp_strval($secret, 16), 96, "0", STR_PAD_LEFT)), 'sha256', true); + return Utils::assumeNotFalse(openssl_digest($salt . hex2bin(str_pad(gmp_strval($secret, 16), 96, "0", STR_PAD_LEFT)), 'sha256', true)); } public static function generateServerHandshakeJwt(\OpenSSLAsymmetricKey $serverPriv, string $salt) : string{ diff --git a/src/network/upnp/UPnP.php b/src/network/upnp/UPnP.php index c2ed90f6e..1c14cead8 100644 --- a/src/network/upnp/UPnP.php +++ b/src/network/upnp/UPnP.php @@ -55,8 +55,8 @@ declare(strict_types=1); */ namespace pocketmine\network\upnp; -use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\Internet; +use pocketmine\utils\Utils; use function count; use function libxml_use_internal_errors; use function parse_url; @@ -99,13 +99,8 @@ class UPnP{ * @throws UPnPException */ public static function getServiceUrl() : string{ - $socket = @socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); - if($socket === false){ - throw new AssumptionFailedError("Socket error: " . trim(socket_strerror(socket_last_error()))); - } - if(!@socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, ["sec" => 3, "usec" => 0])){ - throw new AssumptionFailedError("Socket error: " . trim(socket_strerror(socket_last_error($socket)))); - } + $socket = Utils::assumeNotFalse(@socket_create(AF_INET, SOCK_DGRAM, SOL_UDP), fn() => "Socket error: " . trim(socket_strerror(socket_last_error()))); + Utils::assumeNotFalse(@socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, ["sec" => 3, "usec" => 0]), "Socket error: " . trim(socket_strerror(socket_last_error($socket)))); $contents = "M-SEARCH * HTTP/1.1\r\n" . "MX: 2\r\n" . @@ -171,17 +166,14 @@ class UPnP{ } libxml_use_internal_errors($defaultInternalError); $root->registerXPathNamespace("upnp", "urn:schemas-upnp-org:device-1-0"); - $xpathResult = $root->xpath( + $xpathResult = Utils::assumeNotFalse($root->xpath( '//upnp:device[upnp:deviceType="urn:schemas-upnp-org:device:InternetGatewayDevice:1"]' . '/upnp:deviceList/upnp:device[upnp:deviceType="urn:schemas-upnp-org:device:WANDevice:1"]' . '/upnp:deviceList/upnp:device[upnp:deviceType="urn:schemas-upnp-org:device:WANConnectionDevice:1"]' . '/upnp:serviceList/upnp:service[upnp:serviceType="urn:schemas-upnp-org:service:WANIPConnection:1"]' . '/upnp:controlURL' - ); - if($xpathResult === false){ - //this should be an array of 0 if there is no matching elements; false indicates a problem with the query itself - throw new AssumptionFailedError("xpath query should not error here"); - } + ), "xpath query is borked"); + if(count($xpathResult) === 0){ throw new UPnPException("Your router does not support portforwarding"); } diff --git a/src/permission/BanEntry.php b/src/permission/BanEntry.php index 63858d39c..596edfeb5 100644 --- a/src/permission/BanEntry.php +++ b/src/permission/BanEntry.php @@ -23,7 +23,7 @@ declare(strict_types=1); namespace pocketmine\permission; -use pocketmine\utils\AssumptionFailedError; +use pocketmine\utils\Utils; use function array_shift; use function count; use function explode; @@ -143,8 +143,7 @@ class BanEntry{ private static function parseDate(string $date) : \DateTime{ $datetime = \DateTime::createFromFormat(self::$format, $date); if(!($datetime instanceof \DateTime)){ - $lastErrors = \DateTime::getLastErrors(); - if($lastErrors === false) throw new AssumptionFailedError("DateTime::getLastErrors() should not be returning false in here"); + $lastErrors = Utils::assumeNotFalse(\DateTime::getLastErrors(), "DateTime::getLastErrors() should not be returning false in here"); throw new \RuntimeException("Corrupted date/time: " . implode(", ", $lastErrors["errors"])); } diff --git a/src/plugin/PluginManager.php b/src/plugin/PluginManager.php index de8413097..49f8ed06b 100644 --- a/src/plugin/PluginManager.php +++ b/src/plugin/PluginManager.php @@ -237,8 +237,7 @@ class PluginManager{ $files = iterator_to_array(new \FilesystemIterator($path, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS)); shuffle($files); //this prevents plugins implicitly relying on the filesystem name order when they should be using dependency properties }elseif(is_file($path)){ - $realPath = realpath($path); - if($realPath === false) throw new AssumptionFailedError("realpath() should not return false on an accessible, existing file"); + $realPath = Utils::assumeNotFalse(realpath($path), "realpath() should not return false on an accessible, existing file"); $files = [$realPath]; }else{ return; diff --git a/src/resourcepacks/ZippedResourcePack.php b/src/resourcepacks/ZippedResourcePack.php index 9f2593c84..3642f657e 100644 --- a/src/resourcepacks/ZippedResourcePack.php +++ b/src/resourcepacks/ZippedResourcePack.php @@ -25,6 +25,7 @@ namespace pocketmine\resourcepacks; use Ahc\Json\Comment as CommentedJsonDecoder; use pocketmine\resourcepacks\json\Manifest; +use pocketmine\utils\Utils; use function assert; use function fclose; use function feof; @@ -73,7 +74,7 @@ class ZippedResourcePack implements ResourcePack{ $manifestPath = null; $manifestIdx = null; for($i = 0; $i < $archive->numFiles; ++$i){ - $name = $archive->getNameIndex($i); + $name = Utils::assumeNotFalse($archive->getNameIndex($i), "This index should be valid"); if( ($manifestPath === null or strlen($name) < strlen($manifestPath)) and preg_match('#.*/manifest.json$#', $name) === 1 @@ -156,6 +157,6 @@ class ZippedResourcePack implements ResourcePack{ if(feof($this->fileResource)){ throw new \InvalidArgumentException("Requested a resource pack chunk with invalid start offset"); } - return fread($this->fileResource, $length); + return Utils::assumeNotFalse(fread($this->fileResource, $length), "Already checked that we're not at EOF"); } } diff --git a/src/utils/Filesystem.php b/src/utils/Filesystem.php index fd3eca26b..df50e0134 100644 --- a/src/utils/Filesystem.php +++ b/src/utils/Filesystem.php @@ -79,8 +79,7 @@ final class Filesystem{ public static function recursiveUnlink(string $dir) : void{ if(is_dir($dir)){ - $objects = scandir($dir, SCANDIR_SORT_NONE); - if($objects === false) throw new AssumptionFailedError("scandir() shouldn't return false when is_dir() returns true"); + $objects = Utils::assumeNotFalse(scandir($dir, SCANDIR_SORT_NONE), "scandir() shouldn't return false when is_dir() returns true"); foreach($objects as $object){ if($object !== "." and $object !== ".."){ $fullObject = Path::join($dir, $object); @@ -127,8 +126,7 @@ final class Filesystem{ } mkdir($destination); //TODO: access permissions? } - $objects = scandir($origin, SCANDIR_SORT_NONE); - if($objects === false) throw new AssumptionFailedError("scandir() shouldn't return false when is_dir() returns true"); + $objects = Utils::assumeNotFalse(scandir($origin, SCANDIR_SORT_NONE)); foreach($objects as $object){ if($object === "." || $object === ".."){ continue; @@ -193,7 +191,7 @@ final class Filesystem{ //wait for a shared lock to avoid race conditions if two servers started at the same time - this makes sure the //other server wrote its PID and released exclusive lock before we get our lock flock($resource, LOCK_SH); - $pid = stream_get_contents($resource); + $pid = Utils::assumeNotFalse(stream_get_contents($resource), "This is a known valid file resource, at worst we should receive an empty string"); if(preg_match('/^\d+$/', $pid) === 1){ return (int) $pid; } diff --git a/src/utils/Timezone.php b/src/utils/Timezone.php index fdd39c865..79884751a 100644 --- a/src/utils/Timezone.php +++ b/src/utils/Timezone.php @@ -55,7 +55,7 @@ abstract class Timezone{ } public static function init() : void{ - $timezone = ini_get("date.timezone"); + $timezone = Utils::assumeNotFalse(ini_get("date.timezone"), "date.timezone should always be set in ini"); if($timezone !== ""){ /* * This is here so that people don't come to us complaining and fill up the issue tracker when they put diff --git a/src/world/format/io/data/JavaWorldData.php b/src/world/format/io/data/JavaWorldData.php index cacecae29..e3cb20b6c 100644 --- a/src/world/format/io/data/JavaWorldData.php +++ b/src/world/format/io/data/JavaWorldData.php @@ -29,8 +29,8 @@ use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\FloatTag; use pocketmine\nbt\tag\StringTag; use pocketmine\nbt\TreeRoot; -use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\Filesystem; +use pocketmine\utils\Utils; use pocketmine\world\format\io\exception\CorruptedWorldException; use pocketmine\world\generator\GeneratorManager; use pocketmine\world\World; @@ -112,10 +112,7 @@ class JavaWorldData extends BaseNbtWorldData{ public function save() : void{ $nbt = new BigEndianNbtSerializer(); - $buffer = zlib_encode($nbt->write(new TreeRoot(CompoundTag::create()->setTag("Data", $this->compoundTag))), ZLIB_ENCODING_GZIP); - if($buffer === false){ - throw new AssumptionFailedError("zlib_encode() failed unexpectedly"); - } + $buffer = Utils::assumeNotFalse(zlib_encode($nbt->write(new TreeRoot(CompoundTag::create()->setTag("Data", $this->compoundTag))), ZLIB_ENCODING_GZIP)); Filesystem::safeFilePutContents($this->dataPath, $buffer); } diff --git a/tests/phpstan/configs/actual-problems.neon b/tests/phpstan/configs/actual-problems.neon index bbf723ac2..28e5ca266 100644 --- a/tests/phpstan/configs/actual-problems.neon +++ b/tests/phpstan/configs/actual-problems.neon @@ -1,10 +1,5 @@ parameters: ignoreErrors: - - - message: "#^Parameter \\#3 \\$subject of function preg_replace expects array\\|string, string\\|false given\\.$#" - count: 1 - path: ../../../build/make-release.php - - message: "#^Parameter \\#3 \\$subject of function preg_replace expects array\\|string, string\\|null given\\.$#" count: 2 @@ -20,16 +15,6 @@ parameters: count: 1 path: ../../../build/server-phar.php - - - message: "#^Parameter \\#1 \\$stream of function fclose expects resource, resource\\|false given\\.$#" - count: 1 - path: ../../../src/MemoryManager.php - - - - message: "#^Parameter \\#1 \\$stream of function fwrite expects resource, resource\\|false given\\.$#" - count: 1 - path: ../../../src/MemoryManager.php - - message: "#^Binary operation \"\\.\" between array\\\\|string\\|false and '/'\\|'\\\\\\\\' results in an error\\.$#" count: 2 @@ -40,11 +25,6 @@ parameters: count: 1 path: ../../../src/PocketMine.php - - - message: "#^Parameter \\#1 \\$path of function realpath expects string, string\\|false given\\.$#" - count: 2 - path: ../../../src/PocketMine.php - - message: "#^Cannot cast mixed to string\\.$#" count: 1 @@ -60,11 +40,6 @@ parameters: count: 1 path: ../../../src/Server.php - - - message: "#^Parameter \\#3 \\$subject of function str_replace expects array\\|string, string\\|false given\\.$#" - count: 1 - path: ../../../src/Server.php - - message: "#^Cannot cast array\\\\|string\\|false to string\\.$#" count: 1 @@ -495,21 +470,11 @@ parameters: count: 2 path: ../../../src/console/ConsoleReader.php - - - message: "#^Parameter \\#1 \\$json of function json_decode expects string, string\\|false given\\.$#" - count: 1 - path: ../../../src/crafting/CraftingManagerFromDataHelper.php - - message: "#^Parameter \\#1 \\$path of static method pocketmine\\\\utils\\\\Filesystem\\:\\:cleanPath\\(\\) expects string, mixed given\\.$#" count: 1 path: ../../../src/crash/CrashDump.php - - - message: "#^Parameter \\#1 \\$json of function json_decode expects string, string\\|false given\\.$#" - count: 1 - path: ../../../src/data/bedrock/LegacyToStringBidirectionalIdMap.php - - message: "#^Parameter \\#1 \\$index of method pocketmine\\\\inventory\\\\BaseInventory\\:\\:setItem\\(\\) expects int, int\\|string given\\.$#" count: 1 @@ -615,11 +580,6 @@ parameters: count: 1 path: ../../../src/item/Item.php - - - message: "#^Parameter \\#2 \\$array of function array_map expects array, array\\|false given\\.$#" - count: 1 - path: ../../../src/lang/Language.php - - message: "#^Parameter \\#1 \\$result of method pocketmine\\\\network\\\\mcpe\\\\compression\\\\CompressBatchPromise\\:\\:resolve\\(\\) expects string, mixed given\\.$#" count: 1 @@ -735,16 +695,6 @@ parameters: count: 1 path: ../../../src/network/mcpe/compression/CompressBatchTask.php - - - message: "#^Parameter \\#1 \\$buffer of static method pocketmine\\\\network\\\\mcpe\\\\protocol\\\\serializer\\\\PacketSerializer\\:\\:decoder\\(\\) expects string, string\\|false given\\.$#" - count: 1 - path: ../../../src/network/mcpe/convert/RuntimeBlockMapping.php - - - - message: "#^Method pocketmine\\\\network\\\\mcpe\\\\encryption\\\\EncryptionUtils\\:\\:generateKey\\(\\) should return string but returns string\\|false\\.$#" - count: 1 - path: ../../../src/network/mcpe/encryption/EncryptionUtils.php - - message: "#^Property pocketmine\\\\network\\\\mcpe\\\\encryption\\\\PrepareEncryptionTask\\:\\:\\$serverPrivateKey \\(string\\) does not accept string\\|null\\.$#" count: 1 @@ -865,11 +815,6 @@ parameters: count: 4 path: ../../../src/plugin/PluginManager.php - - - message: "#^Method pocketmine\\\\resourcepacks\\\\ZippedResourcePack\\:\\:getPackChunk\\(\\) should return string but returns string\\|false\\.$#" - count: 1 - path: ../../../src/resourcepacks/ZippedResourcePack.php - - message: "#^Method pocketmine\\\\resourcepacks\\\\ZippedResourcePack\\:\\:getPackSize\\(\\) should return int but returns int\\<0, max\\>\\|false\\.$#" count: 1 @@ -880,11 +825,6 @@ parameters: count: 1 path: ../../../src/resourcepacks/ZippedResourcePack.php - - - message: "#^Parameter \\#1 \\$string of function strlen expects string, string\\|false given\\.$#" - count: 2 - path: ../../../src/resourcepacks/ZippedResourcePack.php - - message: "#^Parameter \\#2 \\$code of class pocketmine\\\\resourcepacks\\\\ResourcePackException constructor expects int, mixed given\\.$#" count: 1 @@ -895,11 +835,6 @@ parameters: count: 1 path: ../../../src/resourcepacks/ZippedResourcePack.php - - - message: "#^Parameter \\#2 \\$subject of function preg_match expects string, string\\|false given\\.$#" - count: 1 - path: ../../../src/resourcepacks/ZippedResourcePack.php - - message: "#^Property pocketmine\\\\resourcepacks\\\\ZippedResourcePack\\:\\:\\$fileResource \\(resource\\) does not accept resource\\|false\\.$#" count: 1 @@ -980,11 +915,6 @@ parameters: count: 1 path: ../../../src/utils/Config.php - - - message: "#^Parameter \\#2 \\$subject of function preg_match expects string, string\\|false given\\.$#" - count: 1 - path: ../../../src/utils/Filesystem.php - - message: "#^Parameter \\#2 \\$offset of function substr expects int, mixed given\\.$#" count: 1 @@ -995,26 +925,11 @@ parameters: count: 1 path: ../../../src/utils/Internet.php - - - message: "#^Parameter \\#1 \\$abbr of function timezone_name_from_abbr expects string, string\\|false given\\.$#" - count: 1 - path: ../../../src/utils/Timezone.php - - - - message: "#^Parameter \\#1 \\$haystack of function strpos expects string, string\\|false given\\.$#" - count: 1 - path: ../../../src/utils/Timezone.php - - message: "#^Parameter \\#1 \\$string of function trim expects string, string\\|false given\\.$#" count: 1 path: ../../../src/utils/Timezone.php - - - message: "#^Parameter \\#1 \\$timezoneId of function date_default_timezone_set expects string, string\\|false given\\.$#" - count: 1 - path: ../../../src/utils/Timezone.php - - message: "#^Cannot cast mixed to string\\.$#" count: 1