diff --git a/rules/S3011/csharp/rule.adoc b/rules/S3011/csharp/rule.adoc index ec7b49f922..ed51dab8b1 100644 --- a/rules/S3011/csharp/rule.adoc +++ b/rules/S3011/csharp/rule.adoc @@ -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[] diff --git a/rules/S3011/description.adoc b/rules/S3011/description.adoc index c210b94893..c83c7a544a 100644 --- a/rules/S3011/description.adoc +++ b/rules/S3011/description.adoc @@ -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. \ No newline at end of file diff --git a/rules/S3011/java/rule.adoc b/rules/S3011/java/rule.adoc index 588f087078..99cc36010e 100644 --- a/rules/S3011/java/rule.adoc +++ b/rules/S3011/java/rule.adoc @@ -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 diff --git a/rules/S3011/php/rule.adoc b/rules/S3011/php/rule.adoc index 21a06b9b01..bf8248755f 100644 --- a/rules/S3011/php/rule.adoc +++ b/rules/S3011/php/rule.adoc @@ -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[] diff --git a/rules/S3011/resources.adoc b/rules/S3011/resources.adoc new file mode 100644 index 0000000000..e9ce459dd2 --- /dev/null +++ b/rules/S3011/resources.adoc @@ -0,0 +1,5 @@ +== Resources + +=== Documentation + +* https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)[Wikipedia definition of Encapsulation] diff --git a/rules/S3011/ruby/metadata.json b/rules/S3011/ruby/metadata.json deleted file mode 100644 index 1797133380..0000000000 --- a/rules/S3011/ruby/metadata.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - -} diff --git a/rules/S3011/ruby/rule.adoc b/rules/S3011/ruby/rule.adoc deleted file mode 100644 index 7883ef8e4c..0000000000 --- a/rules/S3011/ruby/rule.adoc +++ /dev/null @@ -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[] diff --git a/rules/S3011/rule.adoc b/rules/S3011/rule.adoc index 1f1e26aa1b..b129d66df6 100644 --- a/rules/S3011/rule.adoc +++ b/rules/S3011/rule.adoc @@ -2,3 +2,4 @@ include::description.adoc[] +include::resources.adoc[] diff --git a/rules/S3011/vbnet/rule.adoc b/rules/S3011/vbnet/rule.adoc index 4e4fac6f0f..b0e56d69c0 100644 --- a/rules/S3011/vbnet/rule.adoc +++ b/rules/S3011/vbnet/rule.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[]