@@ -44,10 +44,9 @@ PHPAPI zend_class_entry     *spl_ce_MultipleIterator;
4444
4545PHPAPI  zend_object_handlers  spl_handler_SplObjectStorage ;
4646
47- typedef  enum  {
48- 	SOS_OVERRIDDEN_READ_DIMENSION  =  1 ,
49- 	SOS_OVERRIDDEN_WRITE_DIMENSION  =  2 ,
50- } SplObjectStorageBitFlags ;
47+ /* Bit flags for marking internal functionality overridden by SplObjectStorage subclasses. */ 
48+ #define  SOS_OVERRIDDEN_READ_DIMENSION   1
49+ #define  SOS_OVERRIDDEN_WRITE_DIMENSION  2
5150
5251typedef  struct  _spl_SplObjectStorage  { /* {{{ */ 
5352	HashTable          storage ;
@@ -149,16 +148,16 @@ static spl_SplObjectStorageElement *spl_object_storage_create_element(zend_objec
149148static  spl_SplObjectStorageElement  * spl_object_storage_attach_handle (spl_SplObjectStorage  * intern , zend_object  * obj , zval  * inf ) /* {{{ */ 
150149{
151150	uint32_t  handle  =  obj -> handle ;
152- 	zval  * entry_zv ;
151+ 	zval  * entry_zv   =   zend_hash_index_lookup ( & intern -> storage ,  handle ) ;
153152	spl_SplObjectStorageElement  * pelement ;
154- 	entry_zv  =  zend_hash_index_lookup (& intern -> storage , handle );
155153	ZEND_ASSERT (!(intern -> flags  &  SOS_OVERRIDDEN_WRITE_DIMENSION ));
156154
157155	if  (Z_TYPE_P (entry_zv ) !=  IS_NULL ) {
158156		zval  zv_inf ;
159157		ZEND_ASSERT (Z_TYPE_P (entry_zv ) ==  IS_PTR );
160158		pelement  =  Z_PTR_P (entry_zv );
161159		ZVAL_COPY_VALUE (& zv_inf , & pelement -> inf );
160+ 		ZEND_ASSERT (Z_TYPE (zv_inf ) !=  IS_REFERENCE );
162161		if  (inf ) {
163162			ZVAL_COPY (& pelement -> inf , inf );
164163		} else  {
@@ -169,7 +168,6 @@ static spl_SplObjectStorageElement *spl_object_storage_attach_handle(spl_SplObje
169168		return  pelement ;
170169	}
171170
172- 	ZEND_ASSERT ((GC_FLAGS (& intern -> storage ) &  IS_ARRAY_PERSISTENT ) ==  0 );
173171	pelement  =  spl_object_storage_create_element (obj , inf );
174172	ZVAL_PTR (entry_zv , pelement );
175173	return  pelement ;
@@ -193,6 +191,7 @@ spl_SplObjectStorageElement *spl_object_storage_attach(spl_SplObjectStorage *int
193191	if  (pelement ) {
194192		zval  zv_inf ;
195193		ZVAL_COPY_VALUE (& zv_inf , & pelement -> inf );
194+ 		ZEND_ASSERT (Z_TYPE (zv_inf ) !=  IS_REFERENCE );
196195		if  (inf ) {
197196			ZVAL_COPY (& pelement -> inf , inf );
198197		} else  {
@@ -247,8 +246,8 @@ void spl_object_storage_addall(spl_SplObjectStorage *intern, spl_SplObjectStorag
247246	intern -> index  =  0 ;
248247} /* }}} */ 
249248
250- #define  SPL_OBJECT_STORAGE_CLASS_HAS_OVERRIDE (class_type , method ) \
251- 	(((zend_function *)zend_hash_str_find_ptr (&(class_type)->function_table, (method), sizeof((method)) - 1 ))->common.scope != spl_ce_SplObjectStorage)
249+ #define  SPL_OBJECT_STORAGE_CLASS_HAS_OVERRIDE (class_type , zstr_method ) \
250+ 	(((zend_function *)zend_hash_find_ptr (&(class_type)->function_table, ZSTR_KNOWN(zstr_method) ))->common.scope != spl_ce_SplObjectStorage)
252251
253252static  zend_object  * spl_object_storage_new_ex (zend_class_entry  * class_type , zend_object  * orig ) /* {{{ */ 
254253{
@@ -275,14 +274,14 @@ static zend_object *spl_object_storage_new_ex(zend_class_entry *class_type, zend
275274				if  (get_hash -> common .scope  !=  spl_ce_SplObjectStorage ) {
276275					intern -> fptr_get_hash  =  get_hash ;
277276				}
278- 				if  (get_hash  !=  NULL  || 
279- 					SPL_OBJECT_STORAGE_CLASS_HAS_OVERRIDE (class_type , "offsetget" ) || 
280- 					SPL_OBJECT_STORAGE_CLASS_HAS_OVERRIDE (class_type , "offsetexists" )) {
277+ 				if  (intern -> fptr_get_hash  !=  NULL  || 
278+ 					SPL_OBJECT_STORAGE_CLASS_HAS_OVERRIDE (class_type , ZEND_STR_OFFSETGET ) || 
279+ 					SPL_OBJECT_STORAGE_CLASS_HAS_OVERRIDE (class_type , ZEND_STR_OFFSETEXISTS )) {
281280					intern -> flags  |= SOS_OVERRIDDEN_READ_DIMENSION ;
282281				}
283282
284- 				if  (get_hash  !=  NULL  || 
285- 					SPL_OBJECT_STORAGE_CLASS_HAS_OVERRIDE (class_type , "offsetset" )) {
283+ 				if  (intern -> fptr_get_hash  !=  NULL  || 
284+ 					SPL_OBJECT_STORAGE_CLASS_HAS_OVERRIDE (class_type , ZEND_STR_OFFSETSET )) {
286285					intern -> flags  |= SOS_OVERRIDDEN_WRITE_DIMENSION ;
287286				}
288287			}
@@ -401,20 +400,19 @@ static zend_object *spl_SplObjectStorage_new(zend_class_entry *class_type)
401400}
402401/* }}} */ 
403402
404- /* Returns 1  if the SplObjectStorage contains an entry for getHash(obj), even if the corresponding value is null. */ 
405- int  spl_object_storage_contains (spl_SplObjectStorage  * intern , zend_object  * obj ) /* {{{ */ 
403+ /* Returns true  if the SplObjectStorage contains an entry for getHash(obj), even if the corresponding value is null. */ 
404+ bool  spl_object_storage_contains (spl_SplObjectStorage  * intern , zend_object  * obj ) /* {{{ */ 
406405{
407406	if  (EXPECTED (!intern -> fptr_get_hash )) {
408407		return  zend_hash_index_find (& intern -> storage , obj -> handle ) !=  NULL ;
409408	}
410- 	int  found ;
411409	zend_hash_key  key ;
412410	if  (spl_object_storage_get_hash (& key , intern , obj ) ==  FAILURE ) {
413- 		return  0 ;
411+ 		return  true ;
414412	}
415413
416414	ZEND_ASSERT (key .key );
417- 	found  =  zend_hash_exists (& intern -> storage , key .key );
415+ 	bool   found  =  zend_hash_exists (& intern -> storage , key .key );
418416	zend_string_release_ex (key .key , 0 );
419417
420418	return  found ;
@@ -463,17 +461,18 @@ static zval *spl_object_storage_read_dimension(zend_object *object, zval *offset
463461		return  zend_std_read_dimension (object , offset , type , rv );
464462	}
465463	spl_SplObjectStorageElement  * element  =  zend_hash_index_find_ptr (& intern -> storage , Z_OBJ_HANDLE_P (offset ));
466- 	if  (type  ==  BP_VAR_IS ) {
467- 		if  (element  ==  NULL ) {
468- 			return  & EG (uninitialized_zval );
469- 		}
470- 	}
471464
472465	if  (!element ) {
466+ 		if  (type  ==  BP_VAR_IS ) {
467+ 			return  & EG (uninitialized_zval );
468+ 		}
473469		zend_throw_exception_ex (spl_ce_UnexpectedValueException , 0 , "Object not found" );
474470		return  NULL ;
475471	} else  {
476- 		ZVAL_COPY_DEREF (rv , & element -> inf );
472+ 		/* This deliberately returns a non-reference, even for BP_VAR_W and BP_VAR_RW, to behave the same way as SplObjectStorage did when using the default zend_std_read_dimension behavior. 
473+ 		 * i.e. This prevents taking a reference to an entry of SplObjectStorage because offsetGet would return a non-reference. */ 
474+ 		ZEND_ASSERT (Z_TYPE (element -> inf ) !=  IS_REFERENCE );
475+ 		ZVAL_COPY (rv , & element -> inf );
477476		return  rv ;
478477	}
479478}
@@ -538,7 +537,7 @@ PHP_METHOD(SplObjectStorage, offsetGet)
538537	if  (!element ) {
539538		zend_throw_exception_ex (spl_ce_UnexpectedValueException , 0 , "Object not found" );
540539	} else  {
541- 		RETURN_COPY_DEREF (& element -> inf );
540+ 		RETURN_COPY (& element -> inf );
542541	}
543542} /* }}} */ 
544543
0 commit comments