Merge branch 'stable' into next-minor

This commit is contained in:
Dylan K. Taylor 2023-01-12 19:02:07 +00:00
commit d74719704e
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
5 changed files with 133 additions and 60 deletions

View File

@ -50,3 +50,23 @@ Released 6th January 2023.
## Fixes ## Fixes
- Removed a workaround for an old client bug in custom form responses. The code contained a denial-of-service vulnerability. - Removed a workaround for an old client bug in custom form responses. The code contained a denial-of-service vulnerability.
# 4.12.6
Released 7th January 2023.
## Changes
- Added a new security measure to `NetworkSession` to detect and ban players who flood the server with packets.
# 4.12.7
Released 8th January 2023.
## Fixes
- Fixed players getting kicked when the server lags for too long.
- Fixed players getting kicked when a debugging session is active and a breakpoint is hit.
# 4.12.8
Released 9th January 2023.
## Fixes
- Fixed players getting kicked during PvP.
- Fixed players randomly getting kicked on Windows (improper rate limit handling wrt. 15ms timer resolution).

View File

@ -54,7 +54,7 @@
"webmozart/path-util": "^2.3" "webmozart/path-util": "^2.3"
}, },
"require-dev": { "require-dev": {
"phpstan/phpstan": "1.9.7", "phpstan/phpstan": "1.9.11",
"phpstan/phpstan-phpunit": "^1.1.0", "phpstan/phpstan-phpunit": "^1.1.0",
"phpstan/phpstan-strict-rules": "^1.2.0", "phpstan/phpstan-strict-rules": "^1.2.0",
"phpunit/phpunit": "^9.2" "phpunit/phpunit": "^9.2"

127
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "76c6b5521d8f88d9070e8dec1c0ae144", "content-hash": "d5ea4a4f41bf80636b678e6d3d06eac0",
"packages": [ "packages": [
{ {
"name": "adhocore/json-comment", "name": "adhocore/json-comment",
@ -852,42 +852,53 @@
}, },
{ {
"name": "ramsey/collection", "name": "ramsey/collection",
"version": "1.2.2", "version": "1.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/ramsey/collection.git", "url": "https://github.com/ramsey/collection.git",
"reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a" "reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/ramsey/collection/zipball/cccc74ee5e328031b15640b51056ee8d3bb66c0a", "url": "https://api.github.com/repos/ramsey/collection/zipball/ad7475d1c9e70b190ecffc58f2d989416af339b4",
"reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a", "reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.3 || ^8", "php": "^7.4 || ^8.0",
"symfony/polyfill-php81": "^1.23" "symfony/polyfill-php81": "^1.23"
}, },
"require-dev": { "require-dev": {
"captainhook/captainhook": "^5.3", "captainhook/plugin-composer": "^5.3",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", "ergebnis/composer-normalize": "^2.28.3",
"ergebnis/composer-normalize": "^2.6", "fakerphp/faker": "^1.21",
"fakerphp/faker": "^1.5", "hamcrest/hamcrest-php": "^2.0",
"hamcrest/hamcrest-php": "^2", "jangregor/phpstan-prophecy": "^1.0",
"jangregor/phpstan-prophecy": "^0.8", "mockery/mockery": "^1.5",
"mockery/mockery": "^1.3", "php-parallel-lint/php-console-highlighter": "^1.0",
"php-parallel-lint/php-parallel-lint": "^1.3",
"phpcsstandards/phpcsutils": "^1.0.0-rc1",
"phpspec/prophecy-phpunit": "^2.0", "phpspec/prophecy-phpunit": "^2.0",
"phpstan/extension-installer": "^1", "phpstan/extension-installer": "^1.2",
"phpstan/phpstan": "^0.12.32", "phpstan/phpstan": "^1.9",
"phpstan/phpstan-mockery": "^0.12.5", "phpstan/phpstan-mockery": "^1.1",
"phpstan/phpstan-phpunit": "^0.12.11", "phpstan/phpstan-phpunit": "^1.3",
"phpunit/phpunit": "^8.5 || ^9", "phpunit/phpunit": "^9.5",
"psy/psysh": "^0.10.4", "psalm/plugin-mockery": "^1.1",
"slevomat/coding-standard": "^6.3", "psalm/plugin-phpunit": "^0.18.4",
"squizlabs/php_codesniffer": "^3.5", "ramsey/coding-standard": "^2.0.3",
"vimeo/psalm": "^4.4" "ramsey/conventional-commits": "^1.3",
"vimeo/psalm": "^5.4"
}, },
"type": "library", "type": "library",
"extra": {
"captainhook": {
"force-install": true
},
"ramsey/conventional-commits": {
"configFile": "conventional-commits.json"
}
},
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Ramsey\\Collection\\": "src/" "Ramsey\\Collection\\": "src/"
@ -915,7 +926,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/ramsey/collection/issues", "issues": "https://github.com/ramsey/collection/issues",
"source": "https://github.com/ramsey/collection/tree/1.2.2" "source": "https://github.com/ramsey/collection/tree/1.3.0"
}, },
"funding": [ "funding": [
{ {
@ -927,27 +938,27 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-10-10T03:01:02+00:00" "time": "2022-12-27T19:12:24+00:00"
}, },
{ {
"name": "ramsey/uuid", "name": "ramsey/uuid",
"version": "4.6.0", "version": "4.7.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/ramsey/uuid.git", "url": "https://github.com/ramsey/uuid.git",
"reference": "ad63bc700e7d021039e30ce464eba384c4a1d40f" "reference": "433b2014e3979047db08a17a205f410ba3869cf2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/ad63bc700e7d021039e30ce464eba384c4a1d40f", "url": "https://api.github.com/repos/ramsey/uuid/zipball/433b2014e3979047db08a17a205f410ba3869cf2",
"reference": "ad63bc700e7d021039e30ce464eba384c4a1d40f", "reference": "433b2014e3979047db08a17a205f410ba3869cf2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"brick/math": "^0.8.8 || ^0.9 || ^0.10", "brick/math": "^0.8.8 || ^0.9 || ^0.10",
"ext-json": "*", "ext-json": "*",
"php": "^8.0", "php": "^8.0",
"ramsey/collection": "^1.0" "ramsey/collection": "^1.2 || ^2.0"
}, },
"replace": { "replace": {
"rhumsaa/uuid": "self.version" "rhumsaa/uuid": "self.version"
@ -1007,7 +1018,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/ramsey/uuid/issues", "issues": "https://github.com/ramsey/uuid/issues",
"source": "https://github.com/ramsey/uuid/tree/4.6.0" "source": "https://github.com/ramsey/uuid/tree/4.7.3"
}, },
"funding": [ "funding": [
{ {
@ -1019,7 +1030,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-11-05T23:03:38+00:00" "time": "2023-01-12T18:13:24+00:00"
}, },
{ {
"name": "symfony/filesystem", "name": "symfony/filesystem",
@ -1525,30 +1536,30 @@
"packages-dev": [ "packages-dev": [
{ {
"name": "doctrine/instantiator", "name": "doctrine/instantiator",
"version": "1.4.1", "version": "1.5.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/instantiator.git", "url": "https://github.com/doctrine/instantiator.git",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.1 || ^8.0" "php": "^7.1 || ^8.0"
}, },
"require-dev": { "require-dev": {
"doctrine/coding-standard": "^9", "doctrine/coding-standard": "^9 || ^11",
"ext-pdo": "*", "ext-pdo": "*",
"ext-phar": "*", "ext-phar": "*",
"phpbench/phpbench": "^0.16 || ^1", "phpbench/phpbench": "^0.16 || ^1",
"phpstan/phpstan": "^1.4", "phpstan/phpstan": "^1.4",
"phpstan/phpstan-phpunit": "^1", "phpstan/phpstan-phpunit": "^1",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"vimeo/psalm": "^4.22" "vimeo/psalm": "^4.30 || ^5.4"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@ -1575,7 +1586,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/doctrine/instantiator/issues", "issues": "https://github.com/doctrine/instantiator/issues",
"source": "https://github.com/doctrine/instantiator/tree/1.4.1" "source": "https://github.com/doctrine/instantiator/tree/1.5.0"
}, },
"funding": [ "funding": [
{ {
@ -1591,7 +1602,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-03-03T08:28:38+00:00" "time": "2022-12-30T00:15:36+00:00"
}, },
{ {
"name": "myclabs/deep-copy", "name": "myclabs/deep-copy",
@ -1821,16 +1832,16 @@
}, },
{ {
"name": "phpstan/phpstan", "name": "phpstan/phpstan",
"version": "1.9.7", "version": "1.9.11",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpstan.git", "url": "https://github.com/phpstan/phpstan.git",
"reference": "0501435cd342eac7664bd62155b1ef907fc60b6f" "reference": "60f3d68481eef216199eae7a2603cd5fe124d464"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/0501435cd342eac7664bd62155b1ef907fc60b6f", "url": "https://api.github.com/repos/phpstan/phpstan/zipball/60f3d68481eef216199eae7a2603cd5fe124d464",
"reference": "0501435cd342eac7664bd62155b1ef907fc60b6f", "reference": "60f3d68481eef216199eae7a2603cd5fe124d464",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1860,7 +1871,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/phpstan/phpstan/issues", "issues": "https://github.com/phpstan/phpstan/issues",
"source": "https://github.com/phpstan/phpstan/tree/1.9.7" "source": "https://github.com/phpstan/phpstan/tree/1.9.11"
}, },
"funding": [ "funding": [
{ {
@ -1876,7 +1887,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-01-04T21:59:57+00:00" "time": "2023-01-12T14:04:13+00:00"
}, },
{ {
"name": "phpstan/phpstan-phpunit", "name": "phpstan/phpstan-phpunit",
@ -1932,21 +1943,21 @@
}, },
{ {
"name": "phpstan/phpstan-strict-rules", "name": "phpstan/phpstan-strict-rules",
"version": "1.4.4", "version": "1.4.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpstan-strict-rules.git", "url": "https://github.com/phpstan/phpstan-strict-rules.git",
"reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6" "reference": "361f75b06066f3fdaba87c1f57bdb1ffc28d6f1d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6", "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/361f75b06066f3fdaba87c1f57bdb1ffc28d6f1d",
"reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6", "reference": "361f75b06066f3fdaba87c1f57bdb1ffc28d6f1d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.2 || ^8.0", "php": "^7.2 || ^8.0",
"phpstan/phpstan": "^1.8.6" "phpstan/phpstan": "^1.9.7"
}, },
"require-dev": { "require-dev": {
"nikic/php-parser": "^4.13.0", "nikic/php-parser": "^4.13.0",
@ -1974,22 +1985,22 @@
"description": "Extra strict and opinionated rules for PHPStan", "description": "Extra strict and opinionated rules for PHPStan",
"support": { "support": {
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues", "issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.4.4" "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.4.5"
}, },
"time": "2022-09-21T11:38:17+00:00" "time": "2023-01-11T14:16:29+00:00"
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
"version": "9.2.22", "version": "9.2.23",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "e4bf60d2220b4baaa0572986b5d69870226b06df" "reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/e4bf60d2220b4baaa0572986b5d69870226b06df", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c",
"reference": "e4bf60d2220b4baaa0572986b5d69870226b06df", "reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2045,7 +2056,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.22" "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.23"
}, },
"funding": [ "funding": [
{ {
@ -2053,7 +2064,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2022-12-18T16:40:55+00:00" "time": "2022-12-28T12:41:10+00:00"
}, },
{ {
"name": "phpunit/php-file-iterator", "name": "phpunit/php-file-iterator",

View File

@ -31,7 +31,7 @@ use function str_repeat;
final class VersionInfo{ final class VersionInfo{
public const NAME = "PocketMine-MP"; public const NAME = "PocketMine-MP";
public const BASE_VERSION = "4.12.6"; public const BASE_VERSION = "4.12.9";
public const IS_DEVELOPMENT_BUILD = true; public const IS_DEVELOPMENT_BUILD = true;
public const BUILD_CHANNEL = "stable"; public const BUILD_CHANNEL = "stable";

View File

@ -128,20 +128,39 @@ use function array_values;
use function base64_encode; use function base64_encode;
use function bin2hex; use function bin2hex;
use function count; use function count;
use function function_exists;
use function get_class; use function get_class;
use function hrtime;
use function in_array; use function in_array;
use function intdiv;
use function json_encode; use function json_encode;
use function ksort; use function ksort;
use function min;
use function strcasecmp; use function strcasecmp;
use function strlen; use function strlen;
use function strtolower; use function strtolower;
use function substr; use function substr;
use function time; use function time;
use function ucfirst; use function ucfirst;
use function xdebug_is_debugger_active;
use const JSON_THROW_ON_ERROR; use const JSON_THROW_ON_ERROR;
use const SORT_NUMERIC; use const SORT_NUMERIC;
class NetworkSession{ class NetworkSession{
private const INCOMING_PACKET_BATCH_PER_TICK = 2; //usually max 1 per tick, but transactions may arrive separately
private const INCOMING_PACKET_BATCH_MAX_BUDGET = 100; //enough to account for a 5-second lag spike
/**
* At most this many more packets can be received. If this reaches zero, any additional packets received will cause
* the player to be kicked from the server.
* This number is increased every tick up to a maximum limit.
*
* @see self::INCOMING_PACKET_BATCH_PER_TICK
* @see self::INCOMING_PACKET_BATCH_MAX_BUDGET
*/
private int $incomingPacketBatchBudget = self::INCOMING_PACKET_BATCH_MAX_BUDGET;
private int $lastPacketBudgetUpdateTimeNs;
private \PrefixedLogger $logger; private \PrefixedLogger $logger;
private ?Player $player = null; private ?Player $player = null;
private ?PlayerInfo $info = null; private ?PlayerInfo $info = null;
@ -199,6 +218,7 @@ class NetworkSession{
$this->disposeHooks = new ObjectSet(); $this->disposeHooks = new ObjectSet();
$this->connectTime = time(); $this->connectTime = time();
$this->lastPacketBudgetUpdateTimeNs = hrtime(true);
$this->setHandler(new SessionStartPacketHandler( $this->setHandler(new SessionStartPacketHandler(
$this->server, $this->server,
@ -339,6 +359,17 @@ class NetworkSession{
return; return;
} }
if($this->incomingPacketBatchBudget <= 0){
if(!function_exists('xdebug_is_debugger_active') || !xdebug_is_debugger_active()){
throw new PacketHandlingException("Receiving packets too fast");
}else{
//when a debugging session is active, the server may halt at any point for an indefinite length of time,
//in which time the client will continue to send packets
$this->incomingPacketBatchBudget = self::INCOMING_PACKET_BATCH_MAX_BUDGET;
}
}
$this->incomingPacketBatchBudget--;
if($this->cipher !== null){ if($this->cipher !== null){
Timings::$playerNetworkReceiveDecrypt->startTiming(); Timings::$playerNetworkReceiveDecrypt->startTiming();
try{ try{
@ -1138,5 +1169,16 @@ class NetworkSession{
} }
$this->flushSendBuffer(); $this->flushSendBuffer();
$nowNs = hrtime(true);
$timeSinceLastUpdateNs = $nowNs - $this->lastPacketBudgetUpdateTimeNs;
if($timeSinceLastUpdateNs > 50_000_000){
$ticksSinceLastUpdate = intdiv($timeSinceLastUpdateNs, 50_000_000);
$this->incomingPacketBatchBudget = min(
$this->incomingPacketBatchBudget + (self::INCOMING_PACKET_BATCH_PER_TICK * 2 * $ticksSinceLastUpdate),
self::INCOMING_PACKET_BATCH_MAX_BUDGET
);
$this->lastPacketBudgetUpdateTimeNs = $nowNs;
}
} }
} }