Compare commits

..

13 Commits

Author SHA1 Message Date
a4af1609ea Release 3.26.5 2022-01-04 20:47:31 +00:00
8c4b8a9042 CS 2022-01-04 20:44:10 +00:00
958a9dbf0f Merge pull request from GHSA-c6fg-99pr-25m9
* Skin: impose length limits on skinID, geometryName and geometryData fields

* Skin: remove extra newline
2022-01-04 20:40:55 +00:00
68f3399cfd Merge pull request from GHSA-p62j-hrxm-xcxf
This checks the following things:
- Validity of UTF-8 encoding of title, author, and page content
- Maximum soft and hard lengths of title, author, and page content (soft
  limits may be bypassed by uncancelling PlayerEditBookEvent; hard
  limits may not be bypassed)
- Maximum number of pages. Books with more than 50 pages may still be
  edited, but may not have new pages added.
2022-01-04 20:39:02 +00:00
d9c70cb176 start.cmd: prevent idiotic behaviour when paths contain characters such as brackets
god I hate this shit so much
2021-12-27 21:54:32 +00:00
9979a64ad2 3.26.5 is next 2021-12-16 01:23:22 +00:00
75a72786f9 Release 3.26.4 2021-12-16 01:23:21 +00:00
3d205c6e5f Updated transient dependency junk 2021-12-16 01:20:05 +00:00
2955a92837 Updated pocketmine/nbt to 0.2.19 2021-12-16 01:19:30 +00:00
7fb1669c6d php-cs-fixer: added binary_operator_spaces and unary_operator_spaces rules 2021-12-14 23:14:39 +00:00
a09817864b php-cs-fixer: add return_type_declaration space_before 2021-12-14 22:50:43 +00:00
f5bbd30dbb Fixed skins appearing black when using RTX resource packs, closes #4537 2021-12-13 12:35:55 +00:00
69d5bfa0d4 3.26.4 is next 2021-12-10 17:55:11 +00:00
15 changed files with 134 additions and 66 deletions

View File

@ -19,6 +19,9 @@ return (new PhpCsFixer\Config)
'array_syntax' => [
'syntax' => 'short'
],
'binary_operator_spaces' => [
'default' => 'single_space'
],
'blank_line_after_namespace' => true,
'blank_line_after_opening_tag' => true,
'blank_line_before_statement' => [
@ -69,8 +72,12 @@ return (new PhpCsFixer\Config)
],
'phpdoc_trim' => true,
'phpdoc_trim_consecutive_blank_line_separation' => true,
'return_type_declaration' => [
'space_before' => 'one'
],
'single_import_per_statement' => true,
'strict_param' => true,
'unary_operator_spaces' => true,
])
->setFinder($finder)
->setIndent("\t")

View File

@ -21,3 +21,12 @@ Plugin developers should **only** update their required API to this version if y
# 3.26.3
- `PlayerExperienceChangeEvent->setNewProgress()` now performs range checks. This fixes the root of a very old and confusing crash bug which took several years to identify the cause of.
- Note that the defective plugin(s) which caused this problem will still cause a server crash, but the plugin responsible will now get blamed correctly.
# 3.26.4
- Fixed skins appearing black when using RTX resource packs.
- Fixed chunks containing furnaces in old worlds (pre-2017) being discarded as corrupted.
- This was caused by a strict corruption check detecting bad data created by a bug in PocketMine-MP that was fixed in 2017.
# 3.26.5
- Fixed several denial-of-service attack vectors related to writable book text length and encoding.
- Fixed several denial-of-service attack vectors related to skin data field lengths.

View File

@ -33,7 +33,7 @@
"pocketmine/log": "^0.2.0",
"pocketmine/log-pthreads": "^0.1.0",
"pocketmine/math": "^0.2.0",
"pocketmine/nbt": "^0.2.18",
"pocketmine/nbt": "^0.2.19",
"pocketmine/raklib": "^0.12.7",
"pocketmine/snooze": "^0.1.0",
"pocketmine/spl": "^0.4.0"

64
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "2d144524b177c9e7f699ba7366c16354",
"content-hash": "03871ed11c5fe042f6417bceefe9bd4a",
"packages": [
{
"name": "adhocore/json-comment",
@ -322,16 +322,16 @@
},
{
"name": "pocketmine/nbt",
"version": "0.2.18",
"version": "0.2.19",
"source": {
"type": "git",
"url": "https://github.com/pmmp/NBT.git",
"reference": "9f82ca4d7f97fcd9a566e44b63c4f18a7657ae82"
"reference": "8567c65e8e099c2f7436cfea3d886b3dcd332283"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/9f82ca4d7f97fcd9a566e44b63c4f18a7657ae82",
"reference": "9f82ca4d7f97fcd9a566e44b63c4f18a7657ae82",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/8567c65e8e099c2f7436cfea3d886b3dcd332283",
"reference": "8567c65e8e099c2f7436cfea3d886b3dcd332283",
"shasum": ""
},
"require": {
@ -343,7 +343,7 @@
"require-dev": {
"irstea/phpunit-shim": "^7.5 || ^8.0",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "0.12.80",
"phpstan/phpstan": "0.12.85",
"phpstan/phpstan-strict-rules": "^0.12.4"
},
"type": "library",
@ -359,9 +359,9 @@
"description": "PHP library for working with Named Binary Tags",
"support": {
"issues": "https://github.com/pmmp/NBT/issues",
"source": "https://github.com/pmmp/NBT/tree/0.2.18"
"source": "https://github.com/pmmp/NBT/tree/0.2.19"
},
"time": "2021-03-11T00:09:04+00:00"
"time": "2021-12-16T01:15:41+00:00"
},
{
"name": "pocketmine/raklib",
@ -618,16 +618,16 @@
},
{
"name": "nikic/php-parser",
"version": "v4.13.1",
"version": "v4.13.2",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "63a79e8daa781cac14e5195e63ed8ae231dd10fd"
"reference": "210577fe3cf7badcc5814d99455df46564f3c077"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/63a79e8daa781cac14e5195e63ed8ae231dd10fd",
"reference": "63a79e8daa781cac14e5195e63ed8ae231dd10fd",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077",
"reference": "210577fe3cf7badcc5814d99455df46564f3c077",
"shasum": ""
},
"require": {
@ -668,9 +668,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.13.1"
"source": "https://github.com/nikic/PHP-Parser/tree/v4.13.2"
},
"time": "2021-11-03T20:52:16+00:00"
"time": "2021-11-30T19:35:32+00:00"
},
{
"name": "phar-io/manifest",
@ -945,16 +945,16 @@
},
{
"name": "phpspec/prophecy",
"version": "1.14.0",
"version": "v1.15.0",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e"
"reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e",
"reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
"reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
"shasum": ""
},
"require": {
@ -1006,9 +1006,9 @@
],
"support": {
"issues": "https://github.com/phpspec/prophecy/issues",
"source": "https://github.com/phpspec/prophecy/tree/1.14.0"
"source": "https://github.com/phpspec/prophecy/tree/v1.15.0"
},
"time": "2021-09-10T09:02:12+00:00"
"time": "2021-12-08T12:19:24+00:00"
},
{
"name": "phpstan/phpstan",
@ -1182,16 +1182,16 @@
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.9",
"version": "9.2.10",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "f301eb1453c9e7a1bc912ee8b0ea9db22c60223b"
"reference": "d5850aaf931743067f4bfc1ae4cbd06468400687"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f301eb1453c9e7a1bc912ee8b0ea9db22c60223b",
"reference": "f301eb1453c9e7a1bc912ee8b0ea9db22c60223b",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d5850aaf931743067f4bfc1ae4cbd06468400687",
"reference": "d5850aaf931743067f4bfc1ae4cbd06468400687",
"shasum": ""
},
"require": {
@ -1247,7 +1247,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.9"
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.10"
},
"funding": [
{
@ -1255,20 +1255,20 @@
"type": "github"
}
],
"time": "2021-11-19T15:21:02+00:00"
"time": "2021-12-05T09:12:13+00:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "3.0.5",
"version": "3.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "aa4be8575f26070b100fccb67faabb28f21f66f8"
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8",
"reference": "aa4be8575f26070b100fccb67faabb28f21f66f8",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"shasum": ""
},
"require": {
@ -1307,7 +1307,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.5"
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
},
"funding": [
{
@ -1315,7 +1315,7 @@
"type": "github"
}
],
"time": "2020-09-28T05:57:25+00:00"
"time": "2021-12-02T12:48:52+00:00"
},
{
"name": "phpunit/php-invoker",

View File

@ -210,6 +210,7 @@ use function json_encode;
use function json_last_error_msg;
use function lcg_value;
use function max;
use function mb_strlen;
use function microtime;
use function min;
use function preg_match;
@ -3265,6 +3266,24 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
return true;
}
/**
* @throws \UnexpectedValueException
*/
private function checkBookText(string $string, string $fieldName, int $softLimit, int $hardLimit, bool &$cancel) : string{
if(strlen($string) > $hardLimit){
throw new \UnexpectedValueException(sprintf("Book %s must be at most %d bytes, but have %d bytes", $fieldName, $hardLimit, strlen($string)));
}
$result = TextFormat::clean($string, false);
//strlen() is O(1), mb_strlen() is O(n)
if(strlen($result) > $softLimit * 4 || mb_strlen($result, 'UTF-8') > $softLimit){
$cancel = true;
$this->server->getLogger()->debug(sprintf("Cancelled book edit by %s due to %s exceeded soft limit of %d chars", $this->getName(), $fieldName, $softLimit));
}
return $result;
}
public function handleBookEdit(BookEditPacket $packet) : bool{
/** @var WritableBook $oldBook */
$oldBook = $this->inventory->getItem($packet->inventorySlot);
@ -3274,10 +3293,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$newBook = clone $oldBook;
$modifiedPages = [];
$cancel = false;
switch($packet->type){
case BookEditPacket::TYPE_REPLACE_PAGE:
$newBook->setPageText($packet->pageNumber, $packet->text);
$text = self::checkBookText($packet->text, "page text", 256, 0x7fff, $cancel);
$newBook->setPageText($packet->pageNumber, $text);
$modifiedPages[] = $packet->pageNumber;
break;
case BookEditPacket::TYPE_ADD_PAGE:
@ -3286,7 +3306,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
//TODO: the client can send insert-before actions on trailing client-side pages which cause odd behaviour on the server
return false;
}
$newBook->insertPage($packet->pageNumber, $packet->text);
$text = self::checkBookText($packet->text, "page text", 256, 0x7fff, $cancel);
$newBook->insertPage($packet->pageNumber, $text);
$modifiedPages[] = $packet->pageNumber;
break;
case BookEditPacket::TYPE_DELETE_PAGE:
@ -3305,17 +3326,36 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$modifiedPages = [$packet->pageNumber, $packet->secondaryPageNumber];
break;
case BookEditPacket::TYPE_SIGN_BOOK:
$title = self::checkBookText($packet->title, "title", 16, 0x7fff, $cancel);
//this one doesn't have a limit in vanilla, so we have to improvise
$author = self::checkBookText($packet->author, "author", 256, 0x7fff, $cancel);
/** @var WrittenBook $newBook */
$newBook = Item::get(Item::WRITTEN_BOOK, 0, 1, $newBook->getNamedTag());
$newBook->setAuthor($packet->author);
$newBook->setTitle($packet->title);
$newBook->setAuthor($author);
$newBook->setTitle($title);
$newBook->setGeneration(WrittenBook::GENERATION_ORIGINAL);
break;
default:
return false;
}
/*
* Plugins may have created books with more than 50 pages; we allow plugins to do this, but not players.
* Don't allow the page count to grow past 50, but allow deleting, swapping or altering text of existing pages.
*/
$oldPageCount = count($oldBook->getPages());
$newPageCount = count($newBook->getPages());
if(($newPageCount > $oldPageCount && $newPageCount > 50)){
$this->server->getLogger()->debug("Cancelled book edit by " . $this->getName() . " due to adding too many pages (new page count would be $newPageCount)");
$cancel = true;
}
$event = new PlayerEditBookEvent($this, $oldBook, $newBook, $packet->type, $modifiedPages);
if($cancel){
$event->setCancelled();
}
$event->call();
if($event->isCancelled()){
return true;

View File

@ -33,6 +33,6 @@ if(defined('pocketmine\_VERSION_INFO_INCLUDED')){
const _VERSION_INFO_INCLUDED = true;
const NAME = "PocketMine-MP";
const BASE_VERSION = "3.26.3";
const BASE_VERSION = "3.26.5";
const IS_DEVELOPMENT_BUILD = false;
const BUILD_CHANNEL = "pm3";

View File

@ -619,6 +619,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$this->propertyManager->setFloat(self::DATA_SCALE, 1);
$this->propertyManager->setFloat(self::DATA_BOUNDING_BOX_WIDTH, $this->width);
$this->propertyManager->setFloat(self::DATA_BOUNDING_BOX_HEIGHT, $this->height);
$this->propertyManager->setFloat(self::DATA_COLOR, 0);
$this->fireTicks = $this->namedtag->getShort("Fire", 0);
if($this->isOnFire()){
@ -1229,10 +1230,10 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$diffZ = $z - $floorZ;
if(BlockFactory::$solid[$this->level->getBlockIdAt($floorX, $floorY, $floorZ)]){
$westNonSolid = !BlockFactory::$solid[$this->level->getBlockIdAt($floorX - 1, $floorY, $floorZ)];
$eastNonSolid = !BlockFactory::$solid[$this->level->getBlockIdAt($floorX + 1, $floorY, $floorZ)];
$downNonSolid = !BlockFactory::$solid[$this->level->getBlockIdAt($floorX, $floorY - 1, $floorZ)];
$upNonSolid = !BlockFactory::$solid[$this->level->getBlockIdAt($floorX, $floorY + 1, $floorZ)];
$westNonSolid = !BlockFactory::$solid[$this->level->getBlockIdAt($floorX - 1, $floorY, $floorZ)];
$eastNonSolid = !BlockFactory::$solid[$this->level->getBlockIdAt($floorX + 1, $floorY, $floorZ)];
$downNonSolid = !BlockFactory::$solid[$this->level->getBlockIdAt($floorX, $floorY - 1, $floorZ)];
$upNonSolid = !BlockFactory::$solid[$this->level->getBlockIdAt($floorX, $floorY + 1, $floorZ)];
$northNonSolid = !BlockFactory::$solid[$this->level->getBlockIdAt($floorX, $floorY, $floorZ - 1)];
$southNonSolid = !BlockFactory::$solid[$this->level->getBlockIdAt($floorX, $floorY, $floorZ + 1)];

View File

@ -28,6 +28,7 @@ use function implode;
use function in_array;
use function json_encode;
use function strlen;
use const INT32_MAX;
class Skin{
public const ACCEPTED_SKIN_SIZES = [
@ -67,10 +68,20 @@ class Skin{
}
}
private static function checkLength(string $string, string $name, int $maxLength) : void{
if(strlen($string) > $maxLength){
throw new InvalidSkinException("$name must be at most $maxLength bytes, but have " . strlen($string) . " bytes");
}
}
/**
* @throws InvalidSkinException
*/
public function validate() : void{
self::checkLength($this->skinId, "Skin ID", 32767);
self::checkLength($this->geometryName, "Geometry name", 32767);
self::checkLength($this->geometryData, "Geometry data", INT32_MAX);
if($this->skinId === ""){
throw new InvalidSkinException("Skin ID must not be empty");
}

View File

@ -81,7 +81,7 @@ if(!extension_loaded('pocketmine_chunkutils')){
}else{
$i1 = ord($array[$j]);
$i2 = ord($array[$j80]);
$result[$i] = chr(($i2 << 4) | ($i1 & 0x0f));
$result[$i] = chr(($i2 << 4) | ($i1 & 0x0f));
$result[$i | 0x80] = chr(($i1 >> 4) | ($i2 & 0xf0));
}
$i++;

View File

@ -108,9 +108,9 @@ class AdventureSettingsPacket extends DataPacket{
*/
public function setFlag(int $flag, bool $value){
if(($flag & self::BITFLAG_SECOND_SET) !== 0){
$flagSet =& $this->flags2;
$flagSet = &$this->flags2;
}else{
$flagSet =& $this->flags;
$flagSet = &$this->flags;
}
if($value){

View File

@ -48,27 +48,27 @@ class AvailableCommandsPacket extends DataPacket{
* Basic parameter types. These must be combined with the ARG_FLAG_VALID constant.
* ARG_FLAG_VALID | (type const)
*/
public const ARG_TYPE_INT = 0x01;
public const ARG_TYPE_FLOAT = 0x03;
public const ARG_TYPE_VALUE = 0x04;
public const ARG_TYPE_WILDCARD_INT = 0x05;
public const ARG_TYPE_OPERATOR = 0x06;
public const ARG_TYPE_TARGET = 0x07;
public const ARG_TYPE_INT = 0x01;
public const ARG_TYPE_FLOAT = 0x03;
public const ARG_TYPE_VALUE = 0x04;
public const ARG_TYPE_WILDCARD_INT = 0x05;
public const ARG_TYPE_OPERATOR = 0x06;
public const ARG_TYPE_TARGET = 0x07;
public const ARG_TYPE_WILDCARD_TARGET = 0x08;
public const ARG_TYPE_FILEPATH = 0x10;
public const ARG_TYPE_STRING = 0x20;
public const ARG_TYPE_STRING = 0x20;
public const ARG_TYPE_POSITION = 0x28;
public const ARG_TYPE_MESSAGE = 0x2c;
public const ARG_TYPE_MESSAGE = 0x2c;
public const ARG_TYPE_RAWTEXT = 0x2e;
public const ARG_TYPE_RAWTEXT = 0x2e;
public const ARG_TYPE_JSON = 0x32;
public const ARG_TYPE_JSON = 0x32;
public const ARG_TYPE_COMMAND = 0x3f;
public const ARG_TYPE_COMMAND = 0x3f;
/**
* Enums are a little different: they are composed as follows:

View File

@ -106,7 +106,7 @@ class LevelChunkPacket extends DataPacket/* implements ClientboundPacket*/{
$this->subChunkCount = $this->getUnsignedVarInt();
$this->cacheEnabled = $this->getBool();
if($this->cacheEnabled){
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
$this->usedBlobHashes[] = $this->getLLong();
}
}

View File

@ -30,11 +30,11 @@ use pocketmine\network\mcpe\NetworkSession;
class UpdateBlockPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::UPDATE_BLOCK_PACKET;
public const FLAG_NONE = 0b0000;
public const FLAG_NONE = 0b0000;
public const FLAG_NEIGHBORS = 0b0001;
public const FLAG_NETWORK = 0b0010;
public const FLAG_NETWORK = 0b0010;
public const FLAG_NOGRAPHIC = 0b0100;
public const FLAG_PRIORITY = 0b1000;
public const FLAG_PRIORITY = 0b1000;
public const FLAG_ALL = self::FLAG_NEIGHBORS | self::FLAG_NETWORK;
public const FLAG_ALL_PRIORITY = self::FLAG_ALL | self::FLAG_PRIORITY;

View File

@ -368,14 +368,14 @@ class Config{
$this->config[$base] = [];
}
$base =& $this->config[$base];
$base = &$this->config[$base];
while(count($vars) > 0){
$baseKey = array_shift($vars);
if(!isset($base[$baseKey])){
$base[$baseKey] = [];
}
$base =& $base[$baseKey];
$base = &$base[$baseKey];
}
$base = $value;
@ -420,14 +420,14 @@ class Config{
$vars = explode(".", $key);
$currentNode =& $this->config;
$currentNode = &$this->config;
while(count($vars) > 0){
$nodeName = array_shift($vars);
if(isset($currentNode[$nodeName])){
if(count($vars) === 0){ //final node
unset($currentNode[$nodeName]);
}elseif(is_array($currentNode[$nodeName])){
$currentNode =& $currentNode[$nodeName];
$currentNode = &$currentNode[$nodeName];
}
}else{
break;

View File

@ -16,7 +16,7 @@ if exist bin\php\php.exe (
)
if "%PHP_BINARY%"=="" (
echo Couldn't find a PHP binary in system PATH or %~dp0\bin\php
echo Couldn't find a PHP binary in system PATH or "%~dp0bin\php"
echo Please refer to the installation instructions at https://doc.pmmp.io/en/rtfd/installation.html
pause
exit 1