2828#include "php_ini.h"
2929#include "php_reflection.h"
3030#include "ext/standard/info.h"
31+ #include "ext/standard/sha1.h"
32+ #include "ext/standard/php_random.h"
3133
3234#include "zend.h"
3335#include "zend_API.h"
4244#include "zend_builtin_functions.h"
4345#include "zend_smart_str.h"
4446
47+ /* Key used to avoid leaking addresses in ReflectionProperty::getId() */
48+ #define REFLECTION_KEY_LEN 16
49+ ZEND_BEGIN_MODULE_GLOBALS (reflection )
50+ zend_bool key_initialized ;
51+ unsigned char key [REFLECTION_KEY_LEN ];
52+ ZEND_END_MODULE_GLOBALS (reflection )
53+ ZEND_DECLARE_MODULE_GLOBALS (reflection )
54+
55+ #define REFLECTION_G (v ) ZEND_MODULE_GLOBALS_ACCESSOR (reflection , v )
56+
4557#define reflection_update_property (object , name , value ) do { \
4658 zval member ; \
4759 ZVAL_STR (& member , name ); \
@@ -73,6 +85,7 @@ PHPAPI zend_class_entry *reflection_property_ptr;
7385PHPAPI zend_class_entry * reflection_class_constant_ptr ;
7486PHPAPI zend_class_entry * reflection_extension_ptr ;
7587PHPAPI zend_class_entry * reflection_zend_extension_ptr ;
88+ PHPAPI zend_class_entry * reflection_reference_ptr ;
7689
7790/* Exception throwing macro */
7891#define _DO_THROW (msg ) \
@@ -6154,6 +6167,89 @@ ZEND_METHOD(reflection_zend_extension, getCopyright)
61546167}
61556168/* }}} */
61566169
6170+ /* {{{ proto public ReflectionReference::__construct()
6171+ * Dummy constructor -- always throws ReflectionExceptions. */
6172+ ZEND_METHOD (reflection_reference , __construct )
6173+ {
6174+ _DO_THROW (
6175+ "Cannot directly instantiate ReflectionReference. "
6176+ "Use ReflectionReference::fromArrayElement() instead"
6177+ );
6178+ }
6179+ /* }}} */
6180+
6181+ /* {{{ proto public ReflectionReference|null ReflectionReference::fromArrayElement(array array, mixed key)
6182+ * Create ReflectionReference for array item. Returns null if not a reference. */
6183+ ZEND_METHOD (reflection_reference , fromArrayElement )
6184+ {
6185+ HashTable * ht ;
6186+ zval * key , * item ;
6187+ reflection_object * intern ;
6188+
6189+ if (zend_parse_parameters_throw (ZEND_NUM_ARGS (), "hz" , & ht , & key ) == FAILURE ) {
6190+ return ;
6191+ }
6192+
6193+ if (Z_TYPE_P (key ) == IS_LONG ) {
6194+ item = zend_hash_index_find (ht , Z_LVAL_P (key ));
6195+ } else if (Z_TYPE_P (key ) == IS_STRING ) {
6196+ item = zend_symtable_find (ht , Z_STR_P (key ));
6197+ } else {
6198+ zend_type_error ("Key must be array or string" );
6199+ return ;
6200+ }
6201+
6202+ if (!item ) {
6203+ _DO_THROW ("Array key not found" );
6204+ }
6205+
6206+ if (Z_TYPE_P (item ) != IS_REFERENCE ) {
6207+ RETURN_NULL ();
6208+ }
6209+
6210+ object_init_ex (return_value , reflection_reference_ptr );
6211+ intern = Z_REFLECTION_P (return_value );
6212+ ZVAL_COPY (& intern -> obj , item );
6213+ intern -> ref_type = REF_TYPE_OTHER ;
6214+ }
6215+ /* }}} */
6216+
6217+ /* {{{ proto public int|string ReflectionReference::getId()
6218+ * Returns a unique identifier for the reference.
6219+ * The format of the return value is unspecified and may change. */
6220+ ZEND_METHOD (reflection_reference , getId )
6221+ {
6222+ reflection_object * intern ;
6223+ unsigned char digest [20 ];
6224+ PHP_SHA1_CTX context ;
6225+
6226+ if (zend_parse_parameters_none () == FAILURE ) {
6227+ return ;
6228+ }
6229+
6230+ intern = Z_REFLECTION_P (getThis ());
6231+ if (Z_TYPE (intern -> obj ) != IS_REFERENCE ) {
6232+ _DO_THROW ("Corrupted ReflectionReference object" );
6233+ }
6234+
6235+ if (!REFLECTION_G (key_initialized )) {
6236+ if (php_random_bytes_throw (& REFLECTION_G (key_initialized ), 16 ) == FAILURE ) {
6237+ return ;
6238+ }
6239+
6240+ REFLECTION_G (key_initialized ) = 1 ;
6241+ }
6242+
6243+ /* SHA1(ref || key) to avoid directly exposing memory addresses. */
6244+ PHP_SHA1Init (& context );
6245+ PHP_SHA1Update (& context , (unsigned char * ) & Z_REF (intern -> obj ), sizeof (zend_reference * ));
6246+ PHP_SHA1Update (& context , REFLECTION_G (key ), REFLECTION_KEY_LEN );
6247+ PHP_SHA1Final (digest , & context );
6248+
6249+ RETURN_STRINGL ((char * ) digest , sizeof (digest ));
6250+ }
6251+ /* }}} */
6252+
61576253/* {{{ method tables */
61586254static const zend_function_entry reflection_exception_functions [] = {
61596255 PHP_FE_END
@@ -6637,6 +6733,21 @@ static const zend_function_entry reflection_zend_extension_functions[] = {
66376733 ZEND_ME (reflection_zend_extension , getCopyright , arginfo_reflection__void , 0 )
66386734 PHP_FE_END
66396735};
6736+
6737+ ZEND_BEGIN_ARG_INFO_EX (arginfo_reflection_reference_fromArrayElement , 0 , 0 , 2 )
6738+ ZEND_ARG_INFO (0 , array )
6739+ ZEND_ARG_INFO (0 , key )
6740+ ZEND_END_ARG_INFO ()
6741+
6742+ static const zend_function_entry reflection_reference_functions [] = {
6743+ ZEND_ME (reflection_reference , fromArrayElement , arginfo_reflection_reference_fromArrayElement , ZEND_ACC_PUBLIC |ZEND_ACC_STATIC )
6744+ ZEND_ME (reflection_reference , getId , arginfo_reflection__void , ZEND_ACC_PUBLIC )
6745+
6746+ /* Always throwing dummy methods */
6747+ ZEND_ME (reflection , __clone , arginfo_reflection__void , ZEND_ACC_PRIVATE )
6748+ ZEND_ME (reflection_reference , __construct , arginfo_reflection__void , ZEND_ACC_PRIVATE )
6749+ PHP_FE_END
6750+ };
66406751/* }}} */
66416752
66426753static const zend_function_entry reflection_ext_functions [] = { /* {{{ */
@@ -6777,6 +6888,13 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
67776888 zend_class_implements (reflection_zend_extension_ptr , 1 , reflector_ptr );
67786889 zend_declare_property_string (reflection_zend_extension_ptr , "name" , sizeof ("name" )- 1 , "" , ZEND_ACC_PUBLIC );
67796890
6891+ INIT_CLASS_ENTRY (_reflection_entry , "ReflectionReference" , reflection_reference_functions );
6892+ reflection_init_class_handlers (& _reflection_entry );
6893+ _reflection_entry .ce_flags |= ZEND_ACC_FINAL ;
6894+ reflection_reference_ptr = zend_register_internal_class (& _reflection_entry );
6895+
6896+ REFLECTION_G (key_initialized ) = 0 ;
6897+
67806898 return SUCCESS ;
67816899} /* }}} */
67826900
@@ -6797,5 +6915,9 @@ zend_module_entry reflection_module_entry = { /* {{{ */
67976915 NULL ,
67986916 PHP_MINFO (reflection ),
67996917 PHP_REFLECTION_VERSION ,
6800- STANDARD_MODULE_PROPERTIES
6918+ ZEND_MODULE_GLOBALS (reflection ),
6919+ NULL ,
6920+ NULL ,
6921+ NULL ,
6922+ STANDARD_MODULE_PROPERTIES_EX
68016923}; /* }}} */
0 commit comments