@@ -49,10 +49,14 @@ typedef struct _spl_array_object {
4949 unsigned char nApplyCount ;
5050 bool is_child ;
5151 Bucket * bucket ;
52+ /* Overridden ArrayAccess methods */
5253 zend_function * fptr_offset_get ;
5354 zend_function * fptr_offset_set ;
5455 zend_function * fptr_offset_has ;
5556 zend_function * fptr_offset_del ;
57+ /* Overridden append() method */
58+ zend_function * fptr_append ;
59+ /* Overridden count() method */
5660 zend_function * fptr_count ;
5761 zend_class_entry * ce_get_iterator ;
5862 zend_object std ;
@@ -192,6 +196,7 @@ static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zend_o
192196 ZEND_ASSERT (parent );
193197
194198 if (inherited ) {
199+ /* Find potentially overridden ArrayAccess methods */
195200 intern -> fptr_offset_get = zend_hash_str_find_ptr (& class_type -> function_table , "offsetget" , sizeof ("offsetget" ) - 1 );
196201 if (intern -> fptr_offset_get -> common .scope == parent ) {
197202 intern -> fptr_offset_get = NULL ;
@@ -208,7 +213,12 @@ static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zend_o
208213 if (intern -> fptr_offset_del -> common .scope == parent ) {
209214 intern -> fptr_offset_del = NULL ;
210215 }
211- /* Find count() method */
216+ /* Find potentially overridden append() method */
217+ intern -> fptr_append = zend_hash_str_find_ptr (& class_type -> function_table , "append" , sizeof ("append" ) - 1 );
218+ if (intern -> fptr_append -> common .scope == parent ) {
219+ intern -> fptr_append = NULL ;
220+ }
221+ /* Find potentially overridden count() method */
212222 intern -> fptr_count = zend_hash_find_ptr (& class_type -> function_table , ZSTR_KNOWN (ZEND_STR_COUNT ));
213223 if (intern -> fptr_count -> common .scope == parent ) {
214224 intern -> fptr_count = NULL ;
@@ -460,7 +470,7 @@ static uint32_t spl_array_set_refcount(bool is_child, HashTable *ht, uint32_t re
460470 return old_refcount ;
461471} /* }}} */
462472
463- static void spl_array_write_dimension_ex (int check_inherited , zend_object * object , zval * offset , zval * value ) /* {{{ */
473+ static void spl_array_write_dimension_ex (bool check_inherited , zend_object * object , zval * offset , zval * value ) /* {{{ */
464474{
465475 spl_array_object * intern = spl_array_from_obj (object );
466476 HashTable * ht ;
@@ -474,6 +484,20 @@ static void spl_array_write_dimension_ex(int check_inherited, zend_object *objec
474484
475485 /* We are appending */
476486 if (!offset ) {
487+ /* append() method is overridden, so call it */
488+ if (check_inherited && intern -> fptr_append ) {
489+ zend_call_known_function (
490+ intern -> fptr_append ,
491+ object ,
492+ object -> ce ,
493+ /* retval_ptr */ NULL ,
494+ /* param_count */ 1 ,
495+ /* params */ value ,
496+ /* named_params */ NULL
497+ );
498+ return ;
499+ }
500+
477501 /* Cannot append if backing value is an object */
478502 if (spl_array_is_object (intern )) {
479503 zend_throw_error (NULL , "Cannot append properties to objects, use %s::offsetSet() instead" , ZSTR_VAL (object -> ce -> name ));
@@ -491,6 +515,7 @@ static void spl_array_write_dimension_ex(int check_inherited, zend_object *objec
491515 return ;
492516 }
493517
518+ /* offsetSet() method is overridden, so call it */
494519 if (check_inherited && intern -> fptr_offset_set ) {
495520 zend_call_method_with_2_params (object , object -> ce , & intern -> fptr_offset_set , "offsetSet" , NULL , offset , value );
496521 return ;
@@ -542,7 +567,7 @@ static void spl_array_write_dimension_ex(int check_inherited, zend_object *objec
542567
543568static void spl_array_write_dimension (zend_object * object , zval * offset , zval * value ) /* {{{ */
544569{
545- spl_array_write_dimension_ex (1 , object , offset , value );
570+ spl_array_write_dimension_ex (/* check_inherited */ true , object , offset , value );
546571} /* }}} */
547572
548573static void spl_array_unset_dimension_ex (int check_inherited , zend_object * object , zval * offset ) /* {{{ */
@@ -703,9 +728,10 @@ PHP_METHOD(ArrayObject, offsetSet)
703728 if (zend_parse_parameters (ZEND_NUM_ARGS (), "zz" , & index , & value ) == FAILURE ) {
704729 RETURN_THROWS ();
705730 }
706- spl_array_write_dimension_ex (0 , Z_OBJ_P (ZEND_THIS ), index , value );
731+ spl_array_write_dimension_ex (/* check_inherited */ false , Z_OBJ_P (ZEND_THIS ), index , value );
707732} /* }}} */
708733
734+ /* Needed for spl_iterators.c:2938 */
709735void spl_array_iterator_append (zval * object , zval * append_value ) /* {{{ */
710736{
711737 spl_array_write_dimension (Z_OBJ_P (object ), NULL , append_value );
@@ -719,7 +745,7 @@ PHP_METHOD(ArrayObject, append)
719745 if (zend_parse_parameters (ZEND_NUM_ARGS (), "z" , & value ) == FAILURE ) {
720746 RETURN_THROWS ();
721747 }
722- spl_array_iterator_append ( ZEND_THIS , value );
748+ spl_array_write_dimension_ex ( /* check_inherited */ false, Z_OBJ_P ( ZEND_THIS ), /* offset */ NULL , value );
723749} /* }}} */
724750
725751/* {{{ Unsets the value at the specified $index. */
0 commit comments