Modify Rule S3011: LaYC reflection
Co-authored-by: Nils Werner <nils.werner@sonarsource.com>
This commit is contained in:
parent
35036fffff
commit
a08c3bbd23
@ -2,8 +2,6 @@
|
||||
|
||||
include::../description.adoc[]
|
||||
|
||||
=== Noncompliant code example
|
||||
|
||||
[source,csharp]
|
||||
----
|
||||
using System.Reflection;
|
||||
@ -15,6 +13,7 @@ MethodInfo dynMethod = dynClass.GetMethod("mymethod", bindingAttr);
|
||||
object result = dynMethod.Invoke(dynClass, null);
|
||||
----
|
||||
|
||||
include::../resources.adoc[]
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
|
@ -1 +1,3 @@
|
||||
This rule raises an issue when reflection is used to change the visibility of a class, method or field, and when it is used to directly update a field value. Altering or bypassing the accessibility of classes, methods, or fields violates the encapsulation principle and could lead to run-time errors.
|
||||
Altering or bypassing the accessibility of classes, methods, or fields through reflection violates the encapsulation principle. This can break the internal contracts of the accessed target and lead to maintainability issues and runtime errors.
|
||||
|
||||
This rule raises an issue when reflection is used to change the visibility of a class, method or field, and when it is used to directly update a field value.
|
@ -2,8 +2,6 @@
|
||||
|
||||
include::../description.adoc[]
|
||||
|
||||
=== Noncompliant code example
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public void makeItPublic(String methodName) throws NoSuchMethodException {
|
||||
@ -16,7 +14,7 @@ public void setItAnyway(String fieldName, int value) {
|
||||
}
|
||||
----
|
||||
|
||||
== Resources
|
||||
include::../resources.adoc[]
|
||||
|
||||
* https://wiki.sei.cmu.edu/confluence/x/_jZGBQ[CERT, SEC05-J.] - Do not use reflection to increase accessibility of classes, methods, or fields
|
||||
|
||||
|
@ -2,100 +2,16 @@
|
||||
|
||||
include::../description.adoc[]
|
||||
|
||||
=== Noncompliant code example
|
||||
|
||||
[source,php]
|
||||
----
|
||||
class MyClass
|
||||
{
|
||||
public static $publicstatic = 'Static';
|
||||
private static $privatestatic = 'private Static';
|
||||
private $private = 'Private';
|
||||
private const CONST_PRIVATE = 'Private CONST';
|
||||
public $myfield = 42;
|
||||
$reflectionMethod = new ReflectionMethod(MyClass::class, "privateMethode");
|
||||
$reflectionMethod->setAccessible(true);
|
||||
|
||||
private function __construct() {}
|
||||
private function privateMethod() {}
|
||||
public function __set($property, $value) {}
|
||||
public function __get($property) {}
|
||||
}
|
||||
|
||||
$clazz = new ReflectionClass('MyClass');
|
||||
|
||||
$clazz->getstaticProperties(); // Noncompliant . This gives access to private static properties
|
||||
|
||||
$clazz->setStaticPropertyValue('publicstatic', '42'); // OK as there is no overloading to bypass and it respects access control.
|
||||
$clazz->getStaticPropertyValue('publicstatic'); // OK as there is no overloading to bypass and it respects access control.
|
||||
|
||||
// The following calls can access private or protected constants.
|
||||
$clazz->getConstant('CONST_PRIVATE'); // Noncompliant.
|
||||
$clazz->getConstants(); // Noncompliant.
|
||||
$clazz->getReflectionConstant('CONST_PRIVATE'); // Noncompliant.
|
||||
$clazz->getReflectionConstants(); // Noncompliant.
|
||||
|
||||
$obj = $clazz->newInstanceWithoutConstructor(); // Noncompliant. Bypassing private constructor.
|
||||
|
||||
$constructor = $clazz->getConstructor();
|
||||
$constructorClosure = $constructor->getClosure($obj); // Noncompliant. It is possible to call private methods with closures.
|
||||
$constructor->setAccessible(true); // Noncompliant. Bypassing constructor accessibility.
|
||||
|
||||
$prop = new ReflectionProperty('MyClass', 'private');
|
||||
$prop->setAccessible(true); // Noncompliant. Change accessibility of a property.
|
||||
$prop->setValue($obj, "newValue"); // Noncompliant. Bypass of the __set method.
|
||||
$prop->getValue($obj); // Noncompliant. Bypass of the __get method.
|
||||
|
||||
$prop2 = $clazz->getProperties()[2];
|
||||
$prop2->setAccessible(true); // Noncompliant. Change accessibility of a property.
|
||||
$prop2->setValue($obj, "newValue"); // Noncompliant. Bypass of the __set method.
|
||||
$prop2->getValue($obj); // Noncompliant. Bypass of the __get method.
|
||||
|
||||
$meth = new ReflectionMethod('MyClass', 'privateMethod');
|
||||
$clos = $meth->getClosure($obj); // Noncompliant. It is possible to call private methods with closures.
|
||||
$meth->setAccessible(true); // Noncompliant. Change accessibility of a method.
|
||||
|
||||
$meth2 = $clazz->getMethods()[0];
|
||||
$clos2 = $meth2->getClosure($obj); // Noncompliant. It is possible to call private methods with closures.
|
||||
$meth2->setAccessible(true); // Noncompliant. Change accessibility of a method.
|
||||
|
||||
// Using a ReflectionObject instead of the class
|
||||
|
||||
$objr = new ReflectionObject($obj);
|
||||
$objr->newInstanceWithoutConstructor(); // Noncompliant. Bypassing private constructor.
|
||||
|
||||
$objr->getStaticPropertyValue("publicstatic"); // OK as there is no overloading to bypass and it respects access control.
|
||||
$objr->setStaticPropertyValue("publicstatic", "newValue"); // OK as there is no overloading to bypass and it respects access control.
|
||||
|
||||
$objr->getStaticProperties(); // Noncompliant. This gives access to private static properties
|
||||
|
||||
// The following calls can access private or protected constants.
|
||||
$objr->getConstant('CONST_PRIVATE'); // Noncompliant.
|
||||
$objr->getConstants(); // Noncompliant.
|
||||
$objr->getReflectionConstant('CONST_PRIVATE'); // Noncompliant.
|
||||
$objr->getReflectionConstants(); // Noncompliant.
|
||||
|
||||
$constructor = $objr->getConstructor();
|
||||
$constructorClosure = $constructor->getClosure($obj); // Noncompliant. It is possible to call private methods with closures.
|
||||
$constructor->setAccessible(true); // Noncompliant. Bypassing constructor accessibility.
|
||||
|
||||
$prop3 = $objr->getProperty('private');
|
||||
$prop3->setAccessible(true); // Noncompliant. Change accessibility of a property.
|
||||
$prop3->setValue($obj, "newValue"); // Noncompliant. Bypass of the __set method.
|
||||
$prop3->getValue($obj); // Noncompliant. Bypass of the __get method.
|
||||
|
||||
$prop4 = $objr->getProperties()[2];
|
||||
$prop4->setAccessible(true); // Noncompliant. Change accessibility of a property.
|
||||
$prop4->setValue($obj, "newValue"); // Noncompliant. Bypass of the __set method.
|
||||
$prop4->getValue($obj); // Noncompliant. Bypass of the __get method.
|
||||
|
||||
$meth3 = $objr->getMethod('privateMethod');
|
||||
$clos3 = $meth3->getClosure($obj); // Noncompliant. It is possible to call private methods with closures.
|
||||
$meth3->setAccessible(true); // Noncompliant. Change accessibility of a method.
|
||||
|
||||
$meth4 = $objr->getMethods()[0];
|
||||
$clos4 = $meth4->getClosure($obj); // Noncompliant. It is possible to call private methods with closures.
|
||||
$meth4->setAccessible(true); // Noncompliant. Change accessibility of a method.
|
||||
$reflectionProperty = new ReflectionProperty(MyClass::class, "privateProperty");
|
||||
$reflectionProperty->setAccessible(true);
|
||||
----
|
||||
|
||||
include::../resources.adoc[]
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
|
5
rules/S3011/resources.adoc
Normal file
5
rules/S3011/resources.adoc
Normal file
@ -0,0 +1,5 @@
|
||||
== Resources
|
||||
|
||||
=== Documentation
|
||||
|
||||
* https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)[Wikipedia definition of Encapsulation]
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
== Why is this an issue?
|
||||
|
||||
include::../description.adoc[]
|
||||
|
||||
=== Noncompliant code example
|
||||
|
||||
[source,ruby]
|
||||
----
|
||||
class A
|
||||
def mymethod
|
||||
puts "I got called"
|
||||
end
|
||||
private :mymethod
|
||||
end
|
||||
|
||||
a = A.new()
|
||||
# => false
|
||||
puts a.respond_to?(:mymethod)
|
||||
|
||||
class << a
|
||||
public :mymethod # NonCompliant: method was private
|
||||
end
|
||||
# => true
|
||||
puts a.respond_to?(:mymethod)
|
||||
|
||||
b = A.new()
|
||||
# => false
|
||||
puts b.respond_to?(:mymethod)
|
||||
|
||||
A.class_eval do
|
||||
public :mymethod # NonCompliant: method was private
|
||||
end
|
||||
|
||||
c = A.new()
|
||||
# => true
|
||||
puts c.respond_to?(:mymethod)
|
||||
----
|
||||
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
'''
|
||||
== Implementation Specification
|
||||
(visible only on this page)
|
||||
|
||||
include::../message.adoc[]
|
||||
|
||||
'''
|
||||
== Comments And Links
|
||||
(visible only on this page)
|
||||
|
||||
include::../comments-and-links.adoc[]
|
||||
endif::env-github,rspecator-view[]
|
@ -2,3 +2,4 @@
|
||||
|
||||
include::description.adoc[]
|
||||
|
||||
include::resources.adoc[]
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
include::../description.adoc[]
|
||||
|
||||
=== Noncompliant code example
|
||||
|
||||
[source,vbnet]
|
||||
----
|
||||
Imports System.Reflection
|
||||
@ -15,6 +13,8 @@ Dim dynMethod As MethodInfo = dynClass.GetMethod("mymethod", bindingAttr)
|
||||
Dim result = dynMethod.Invoke(dynClass, Nothing)
|
||||
----
|
||||
|
||||
include::../resources.adoc[]
|
||||
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user