rfc:reference_reflection

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:reference_reflection [2019/01/15 10:41] – Make final, mention exceptions nikicrfc:reference_reflection [2019/02/13 11:26] (current) – Implemented nikic
Line 2: Line 2:
   * Date: 2019-01-15   * Date: 2019-01-15
   * Author: Nikita Popov <nikic@php.net>   * Author: Nikita Popov <nikic@php.net>
-  * Status: Under Discussion+  * Status: Implemented (in PHP 7.4)
   * Targets: PHP 7.4   * Targets: PHP 7.4
   * PR: https://github.com/php/php-src/pull/3550   * PR: https://github.com/php/php-src/pull/3550
Line 24: Line 24:
 While this approach currently works, it is slow and convoluted. To make matters worse, this approach will no longer work reliably in PHP 7.4, due to the introduction of [[rfc:typed_properties_v2|typed properties]]. If ''$array1[$key]'' is a reference to a property with a certain type, then the assignment of the cookie may trigger a ''TypeError''. While this approach currently works, it is slow and convoluted. To make matters worse, this approach will no longer work reliably in PHP 7.4, due to the introduction of [[rfc:typed_properties_v2|typed properties]]. If ''$array1[$key]'' is a reference to a property with a certain type, then the assignment of the cookie may trigger a ''TypeError''.
  
-This RFC proposed to introduce a first-class API for reflection of references, to solve this type of rare, but also fundamental problem.+This RFC proposes to introduce a first-class API for reflection of references, to solve this type of rare, but also fundamental problem.
  
 ===== Proposal ===== ===== Proposal =====
Line 33: Line 33:
 final class ReflectionReference { final class ReflectionReference {
     /* Returns ReflectionReference if array element is a reference, null otherwise. */     /* Returns ReflectionReference if array element is a reference, null otherwise. */
-    public static function fromArrayElem(array $array, int|string $key): ?ReflectionReference;+    public static function fromArrayElement(array $array, int|string $key): ?ReflectionReference;
          
     /* Returns unique identifier for the reference. The return value format is unspecified. */     /* Returns unique identifier for the reference. The return value format is unspecified. */
     public function getId(): int|string;     public function getId(): int|string;
  
-    public function __construct(); // Always throws+    private function __construct(); // Always throws
     private function __clone(); // Always throws     private function __clone(); // Always throws
 } }
Line 49: Line 49:
 Construction of ''ReflectionReference'' instances faces the following problem: A PHP function can either accept an argument by value or by reference. This needs to be declared in the function signature, making it impossible to distinguish whether the passed value was a reference originally or not. To determine whether or not something is a reference, access to the parent structure is necessary (which might be an array, object property table or symbol table). Construction of ''ReflectionReference'' instances faces the following problem: A PHP function can either accept an argument by value or by reference. This needs to be declared in the function signature, making it impossible to distinguish whether the passed value was a reference originally or not. To determine whether or not something is a reference, access to the parent structure is necessary (which might be an array, object property table or symbol table).
  
-To start with, only the ''fromArrayElem($array, $key)'' API is provided, which covers all known use-cases. Object properties can be handled by casting the object to array. The ''fromArrayElem($array, $key)'' method will either return a ''ReflectionReference'' instance if ''$array[$key]'' is a reference, or null.+To start with, only the ''fromArrayElement($array, $key)'' API is provided, which covers all known use-cases. Object properties can be handled by casting the object to array. The ''fromArrayElement($array, $key)'' method will either return a ''ReflectionReference'' instance if ''$array[$key]'' is a reference, or null.
  
 If ''$array'' is not an array or ''$key'' is not an integer or string, a ''TypeError'' is thrown. If ''$array[$key]'' does not exist, a ''ReflectionException'' is thrown. If ''$array'' is not an array or ''$key'' is not an integer or string, a ''TypeError'' is thrown. If ''$array[$key]'' does not exist, a ''ReflectionException'' is thrown.
Line 70: Line 70:
 </code> </code>
  
-The value returned by ''getId()'' is based on the address of the ''zend_reference'' structure, which is used internally to represent references. To avoid directly leaking memory addresses, which would facilitate attacks requiring knowledge of memory layout, the address is SHA1 hashed together with a per-process 128-bit key. The raw 20 byte digest is returned (not hex encoded). In other words, the return value of ''getId()'' is ''sha1(address_of($ref) . $key, true)''. As mentioned above, the specific scheme used here is an implementation detail and may change in the future.+The value returned by ''getId()'' is based on the address of the ''zend_reference'' structure, which is used internally to represent references. To avoid directly leaking memory addresses, which would facilitate attacks requiring knowledge of memory layout, the address is SHA1 hashed together with a per-process 128-bit key. The raw 20 byte digest is returned (not hex encoded). In other words, the return value of ''getId()'' is ''sha1(address_of($ref) . $key, true)''. 
 + 
 +As mentioned above, the specific scheme used here is an implementation detail and may change in the future. The length of the string may change, and the return value may be converted into an integer in the future, if it becomes technically feasible.
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
Line 85: Line 87:
 ===== Vote ===== ===== Vote =====
  
-Add ''ReflectionReference'' class as described? A 2/3 majority is required.+Add ''ReflectionReference'' class as described? A 2/3 majority is required. The vote started 2019-01-30 and will end 2019-02-13. 
 + 
 +<doodle title="Add ReflectionReference?" auth="nikic" voteType="single" closed="true"> 
 +   * Yes 
 +   * No 
 +</doodle>
rfc/reference_reflection.1547548863.txt.gz · Last modified: 2019/01/15 10:41 by nikic