From be078c69ace0047d357fe1e9dc96e638b891b2f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C5=A0pa=C4=8Dek?= Date: Fri, 6 Dec 2024 00:54:50 +0100 Subject: [PATCH 1/4] Test disallowed constants on anonymous child classes, already detected, but now as "class@anonymous" similar to what get_class() returns --- src/Usages/ClassConstantUsages.php | 4 +++- tests/Usages/ClassConstantUsagesTest.php | 4 ++++ tests/src/disallowed-allow/constantUsages.php | 4 ++++ tests/src/disallowed/constantUsages.php | 4 ++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Usages/ClassConstantUsages.php b/src/Usages/ClassConstantUsages.php index ed0c8de..abe32b0 100644 --- a/src/Usages/ClassConstantUsages.php +++ b/src/Usages/ClassConstantUsages.php @@ -108,7 +108,9 @@ private function getConstantRuleErrors(Scope $scope, string $constant, Type $typ } $usedOnType = $type->getObjectTypeOrClassStringObjectType(); - $displayName = $usedOnType->getObjectClassNames() ? $this->getFullyQualified($usedOnType->getObjectClassNames(), $constant) : null; + $classes = $usedOnType->getObjectClassReflections(); + $classNames = array_map(fn($class): string => $class->isAnonymous() ? 'class@anonymous' : $class->getName(), $classes); + $displayName = $classNames ? $this->getFullyQualified($classNames, $constant) : null; if ($usedOnType->getConstantStrings()) { $classNames = array_map( function (ConstantStringType $constantString): string { diff --git a/tests/Usages/ClassConstantUsagesTest.php b/tests/Usages/ClassConstantUsagesTest.php index f487ddf..5af27fc 100644 --- a/tests/Usages/ClassConstantUsagesTest.php +++ b/tests/Usages/ClassConstantUsagesTest.php @@ -136,6 +136,10 @@ public function testRule(): void 'Using PhpOption\Option::NAME (as PhpOption\None::NAME) is forbidden, no PhpOption.', 37, ], + [ + 'Using Inheritance\Base::BELONG (as class@anonymous::BELONG) is forbidden, belong to us.', + 44, + ], ]); $this->analyse([__DIR__ . '/../src/disallowed-allow/constantUsages.php'], []); } diff --git a/tests/src/disallowed-allow/constantUsages.php b/tests/src/disallowed-allow/constantUsages.php index 1865a8e..5780a25 100644 --- a/tests/src/disallowed-allow/constantUsages.php +++ b/tests/src/disallowed-allow/constantUsages.php @@ -38,3 +38,7 @@ // not disallowed by path PHP_EOL; + +// allowed by path +$foo = new class extends Base {}; +$foo::BELONG; diff --git a/tests/src/disallowed/constantUsages.php b/tests/src/disallowed/constantUsages.php index 0e50d92..b4e5538 100644 --- a/tests/src/disallowed/constantUsages.php +++ b/tests/src/disallowed/constantUsages.php @@ -38,3 +38,7 @@ // disallowed by path PHP_EOL; + +// disallowed +$foo = new class extends Base {}; +$foo::BELONG; From db546f41499a0b80403820d2a50f6050c8acbd88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C5=A0pa=C4=8Dek?= Date: Fri, 6 Dec 2024 01:14:53 +0100 Subject: [PATCH 2/4] Test disallowed method calls on anonymous classes, already detected but now as "class@anonymous" similar to what get_class() returns --- src/RuleErrors/DisallowedMethodRuleErrors.php | 3 ++- tests/Calls/MethodCallsTest.php | 8 ++++++++ tests/Calls/StaticCallsTest.php | 8 ++++++++ tests/src/disallowed-allow/methodCalls.php | 17 +++++++++++++++++ tests/src/disallowed-allow/staticCalls.php | 17 +++++++++++++++++ tests/src/disallowed/methodCalls.php | 17 +++++++++++++++++ tests/src/disallowed/staticCalls.php | 17 +++++++++++++++++ 7 files changed, 86 insertions(+), 1 deletion(-) diff --git a/src/RuleErrors/DisallowedMethodRuleErrors.php b/src/RuleErrors/DisallowedMethodRuleErrors.php index eb80b6b..2df5b86 100644 --- a/src/RuleErrors/DisallowedMethodRuleErrors.php +++ b/src/RuleErrors/DisallowedMethodRuleErrors.php @@ -57,7 +57,8 @@ public function get($class, CallLike $node, Scope $scope, array $disallowedCalls if ($calledOnType->canCallMethods()->yes() && $calledOnType->hasMethod($node->name->name)->yes()) { $method = $calledOnType->getMethod($node->name->name, $scope); $declaringClass = $method->getDeclaringClass(); - $classNames = $calledOnType->getObjectClassNames(); + $classes = $calledOnType->getObjectClassReflections(); + $classNames = array_map(fn($class): string => $class->isAnonymous() ? 'class@anonymous' : $class->getName(), $classes); if (count($classNames) === 0) { $calledAs = null; } else { diff --git a/tests/Calls/MethodCallsTest.php b/tests/Calls/MethodCallsTest.php index 87b3937..d5f8d74 100644 --- a/tests/Calls/MethodCallsTest.php +++ b/tests/Calls/MethodCallsTest.php @@ -213,6 +213,14 @@ public function testRule(): void 'Calling Interfaces\BaseInterface::x() (as Interfaces\Implementation::x()) is forbidden, BaseInterface::x*() methods are dangerous. [Interfaces\BaseInterface::x() matches Interfaces\BaseInterface::x*()]', 74, ], + [ + 'Calling Interfaces\BaseInterface::x() (as class@anonymous::x()) is forbidden, BaseInterface::x*() methods are dangerous. [Interfaces\BaseInterface::x() matches Interfaces\BaseInterface::x*()]', + 87, + ], + [ + 'Calling Inheritance\Base::x() (as class@anonymous::x()) is forbidden, Base::x*() methods are dangerous. [Inheritance\Base::x() matches Inheritance\Base::x*()]', + 91, + ], ]); $this->analyse([__DIR__ . '/../src/disallowed-allow/methodCalls.php'], [ [ diff --git a/tests/Calls/StaticCallsTest.php b/tests/Calls/StaticCallsTest.php index cbb4dd6..6098859 100644 --- a/tests/Calls/StaticCallsTest.php +++ b/tests/Calls/StaticCallsTest.php @@ -177,6 +177,14 @@ public function testRule(): void 'Calling Interfaces\BaseInterface::y() (as Interfaces\Implementation::y()) is forbidden, method BaseInterface::y() is dangerous. [Interfaces\BaseInterface::y() matches Interfaces\BaseInterface::y*()]', 40, ], + [ + 'Calling Interfaces\BaseInterface::y() (as class@anonymous::y()) is forbidden, method BaseInterface::y() is dangerous. [Interfaces\BaseInterface::y() matches Interfaces\BaseInterface::y*()]', + 53, + ], + [ + 'Calling Inheritance\Base::woofer() (as class@anonymous::woofer()) is forbidden, method Base::woofer() is dangerous. [Inheritance\Base::woofer() matches Inheritance\Base::w*f*r()]', + 57, + ], ]); $this->analyse([__DIR__ . '/../src/disallowed-allow/staticCalls.php'], [ [ diff --git a/tests/src/disallowed-allow/methodCalls.php b/tests/src/disallowed-allow/methodCalls.php index 134b4c7..05f87d9 100644 --- a/tests/src/disallowed-allow/methodCalls.php +++ b/tests/src/disallowed-allow/methodCalls.php @@ -72,3 +72,20 @@ // allowed by path (new Interfaces\Implementation())->x(); +$foo = new class implements Interfaces\BaseInterface { + + public function x(): void + { + } + + + public static function y(): void + { + } + +}; +$foo->x(); + +// allowed by path +$foo = new class extends Inheritance\Base {}; +$foo->x(); diff --git a/tests/src/disallowed-allow/staticCalls.php b/tests/src/disallowed-allow/staticCalls.php index 7b589f3..54a8179 100644 --- a/tests/src/disallowed-allow/staticCalls.php +++ b/tests/src/disallowed-allow/staticCalls.php @@ -38,3 +38,20 @@ // interface method allowed by path Interfaces\Implementation::y(); +$foo = new class implements Interfaces\BaseInterface { + + public function x(): void + { + } + + + public static function y(): void + { + } + +}; +$foo::y(); + +// allowed by path +$foo = new class extends Inheritance\Base {}; +$foo::woofer(); diff --git a/tests/src/disallowed/methodCalls.php b/tests/src/disallowed/methodCalls.php index d244941..ef3af71 100644 --- a/tests/src/disallowed/methodCalls.php +++ b/tests/src/disallowed/methodCalls.php @@ -72,3 +72,20 @@ // disallowed interface method (new Interfaces\Implementation())->x(); +$foo = new class implements Interfaces\BaseInterface { + + public function x(): void + { + } + + + public static function y(): void + { + } + +}; +$foo->x(); + +// disallowed parent method +$foo = new class extends Inheritance\Base {}; +$foo->x(); diff --git a/tests/src/disallowed/staticCalls.php b/tests/src/disallowed/staticCalls.php index 5014f5c..a52666c 100644 --- a/tests/src/disallowed/staticCalls.php +++ b/tests/src/disallowed/staticCalls.php @@ -38,3 +38,20 @@ // disallowed on interface Interfaces\Implementation::y(); +$foo = new class implements Interfaces\BaseInterface { + + public function x(): void + { + } + + + public static function y(): void + { + } + +}; +$foo::y(); + +// disallowed parent method +$foo = new class extends Inheritance\Base {}; +$foo::woofer(); From 2ac072ec11f6ca193ec7cb25a98b4ab00ad2324d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C5=A0pa=C4=8Dek?= Date: Fri, 6 Dec 2024 02:02:30 +0100 Subject: [PATCH 3/4] Add the missing methods do -allow directory too --- tests/src/disallowed-allow/namespaceUsages.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/src/disallowed-allow/namespaceUsages.php b/tests/src/disallowed-allow/namespaceUsages.php index b899a30..edee8f6 100644 --- a/tests/src/disallowed-allow/namespaceUsages.php +++ b/tests/src/disallowed-allow/namespaceUsages.php @@ -9,6 +9,7 @@ use Traits\TestTrait; use Waldo\Foo\Bar; use Waldo\Quux\blade; +use ZipArchive; class Service extends Base implements SomeInterface { @@ -37,4 +38,16 @@ public function callConstant() return Bar::NAME; } + + public function callNew() + { + return new Bar(); + } + + + public function disallowedByPath() + { + return ZipArchive::EM_TRAD_PKWARE; + } + } From 3b45f4d2f016fae5a40f9d017b06fdb81be92731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C5=A0pa=C4=8Dek?= Date: Fri, 6 Dec 2024 03:11:49 +0100 Subject: [PATCH 4/4] Test anonymous class inheriting from a disallowed class, already detected --- tests/Usages/NamespaceUsagesTest.php | 4 ++++ tests/src/disallowed-allow/namespaceUsages.php | 6 ++++++ tests/src/disallowed/namespaceUsages.php | 6 ++++++ 3 files changed, 16 insertions(+) diff --git a/tests/Usages/NamespaceUsagesTest.php b/tests/Usages/NamespaceUsagesTest.php index 1e8c8da..a2f5aea 100644 --- a/tests/Usages/NamespaceUsagesTest.php +++ b/tests/Usages/NamespaceUsagesTest.php @@ -145,6 +145,10 @@ public function testRule(): void 'Class ZipArchive is forbidden, use clippy instead of zippy.', 50, ], + [ + 'Namespace Inheritance\Base is forbidden, no inheritance sub base.', + 56, + ], ]); $this->analyse([__DIR__ . '/../src/disallowed-allow/namespaceUsages.php'], []); } diff --git a/tests/src/disallowed-allow/namespaceUsages.php b/tests/src/disallowed-allow/namespaceUsages.php index edee8f6..974fafb 100644 --- a/tests/src/disallowed-allow/namespaceUsages.php +++ b/tests/src/disallowed-allow/namespaceUsages.php @@ -50,4 +50,10 @@ public function disallowedByPath() return ZipArchive::EM_TRAD_PKWARE; } + + public function anonymousClass() + { + return new class extends Base {}; + } + } diff --git a/tests/src/disallowed/namespaceUsages.php b/tests/src/disallowed/namespaceUsages.php index edee8f6..974fafb 100644 --- a/tests/src/disallowed/namespaceUsages.php +++ b/tests/src/disallowed/namespaceUsages.php @@ -50,4 +50,10 @@ public function disallowedByPath() return ZipArchive::EM_TRAD_PKWARE; } + + public function anonymousClass() + { + return new class extends Base {}; + } + }