From 8ec2ba79de0c0f0fa43c8210b286e86ca33eb4ca Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 21 May 2020 11:38:02 +0100 Subject: [PATCH] Unhackify Registry member cloning, fixes #3519 --- src/block/VanillaBlocks.php | 8 +-- src/item/VanillaItems.php | 8 +-- src/utils/CloningRegistryTrait.php | 32 +++++++++++ src/utils/RegistryTrait.php | 11 +++- .../utils/CloningRegistryTraitTest.php | 55 +++++++++++++++++++ tests/phpunit/utils/TestCloningRegistry.php | 54 ++++++++++++++++++ 6 files changed, 158 insertions(+), 10 deletions(-) create mode 100644 src/utils/CloningRegistryTrait.php create mode 100644 tests/phpunit/utils/CloningRegistryTraitTest.php create mode 100644 tests/phpunit/utils/TestCloningRegistry.php diff --git a/src/block/VanillaBlocks.php b/src/block/VanillaBlocks.php index 5da766624..3371a7d25 100644 --- a/src/block/VanillaBlocks.php +++ b/src/block/VanillaBlocks.php @@ -23,8 +23,8 @@ declare(strict_types=1); namespace pocketmine\block; +use pocketmine\utils\CloningRegistryTrait; use pocketmine\utils\RegistryTrait; -use pocketmine\utils\Utils; use function assert; /** @@ -665,7 +665,7 @@ use function assert; * @method static Wool YELLOW_WOOL() */ final class VanillaBlocks{ - use RegistryTrait; + use CloningRegistryTrait; private function __construct(){ //NOOP @@ -678,14 +678,14 @@ final class VanillaBlocks{ public static function fromString(string $name) : Block{ $result = self::_registryFromString($name); assert($result instanceof Block); - return clone $result; + return $result; } /** * @return Block[] */ public static function getAll() : array{ - return Utils::cloneObjectArray(self::_registryGetAll()); + return self::_registryGetAll(); } protected static function setup() : void{ diff --git a/src/item/VanillaItems.php b/src/item/VanillaItems.php index d8bb6b655..a95604b8e 100644 --- a/src/item/VanillaItems.php +++ b/src/item/VanillaItems.php @@ -23,8 +23,8 @@ declare(strict_types=1); namespace pocketmine\item; +use pocketmine\utils\CloningRegistryTrait; use pocketmine\utils\RegistryTrait; -use pocketmine\utils\Utils; use function assert; /** @@ -292,7 +292,7 @@ use function assert; * @method static Skull ZOMBIE_HEAD() */ final class VanillaItems{ - use RegistryTrait; + use CloningRegistryTrait; private function __construct(){ //NOOP @@ -305,14 +305,14 @@ final class VanillaItems{ public static function fromString(string $name) : Item{ $result = self::_registryFromString($name); assert($result instanceof Item); - return clone $result; + return $result; } /** * @return Item[] */ public static function getAll() : array{ - return Utils::cloneObjectArray(self::_registryGetAll()); + return self::_registryGetAll(); } protected static function setup() : void{ diff --git a/src/utils/CloningRegistryTrait.php b/src/utils/CloningRegistryTrait.php new file mode 100644 index 000000000..af815658e --- /dev/null +++ b/src/utils/CloningRegistryTrait.php @@ -0,0 +1,32 @@ + + */ + public function cloningRegistryMembersProvider() : \Generator{ + yield [function() : \stdClass{ return TestCloningRegistry::TEST1(); }]; + yield [function() : \stdClass{ return TestCloningRegistry::TEST2(); }]; + yield [function() : \stdClass{ return TestCloningRegistry::TEST3(); }]; + } + + /** + * @dataProvider cloningRegistryMembersProvider + * @phpstan-param \Closure() : \stdClass $provider + */ + public function testEachMemberClone(\Closure $provider) : void{ + self::assertNotSame($provider(), $provider(), "Cloning registry should never return the same object twice"); + } + + public function testGetAllClone() : void{ + $list1 = TestCloningRegistry::getAll(); + $list2 = TestCloningRegistry::getAll(); + foreach($list1 as $k => $member){ + self::assertNotSame($member, $list2[$k], "VanillaBlocks ought to clone its members"); + } + } +} diff --git a/tests/phpunit/utils/TestCloningRegistry.php b/tests/phpunit/utils/TestCloningRegistry.php new file mode 100644 index 000000000..5683fd11b --- /dev/null +++ b/tests/phpunit/utils/TestCloningRegistry.php @@ -0,0 +1,54 @@ +