Modify Rule S3011: LaYC reflection

Co-authored-by: Nils Werner <nils.werner@sonarsource.com>
This commit is contained in:
Fred Tingaud 2023-06-13 19:24:21 +02:00 committed by GitHub
parent 35036fffff
commit a08c3bbd23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 18 additions and 153 deletions

View File

@ -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[]

View File

@ -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.

View File

@ -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

View File

@ -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[]

View File

@ -0,0 +1,5 @@
== Resources
=== Documentation
* https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)[Wikipedia definition of Encapsulation]

View File

@ -1,3 +0,0 @@
{
}

View File

@ -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[]

View File

@ -2,3 +2,4 @@
include::description.adoc[]
include::resources.adoc[]

View File

@ -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[]