@@ -49,10 +49,14 @@ typedef struct _spl_array_object {
49
49
unsigned char nApplyCount ;
50
50
bool is_child ;
51
51
Bucket * bucket ;
52
+ /* Overridden ArrayAccess methods */
52
53
zend_function * fptr_offset_get ;
53
54
zend_function * fptr_offset_set ;
54
55
zend_function * fptr_offset_has ;
55
56
zend_function * fptr_offset_del ;
57
+ /* Overridden append() method */
58
+ zend_function * fptr_append ;
59
+ /* Overridden count() method */
56
60
zend_function * fptr_count ;
57
61
zend_class_entry * ce_get_iterator ;
58
62
zend_object std ;
@@ -192,6 +196,7 @@ static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zend_o
192
196
ZEND_ASSERT (parent );
193
197
194
198
if (inherited ) {
199
+ /* Find potentially overridden ArrayAccess methods */
195
200
intern -> fptr_offset_get = zend_hash_str_find_ptr (& class_type -> function_table , "offsetget" , sizeof ("offsetget" ) - 1 );
196
201
if (intern -> fptr_offset_get -> common .scope == parent ) {
197
202
intern -> fptr_offset_get = NULL ;
@@ -208,7 +213,12 @@ static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zend_o
208
213
if (intern -> fptr_offset_del -> common .scope == parent ) {
209
214
intern -> fptr_offset_del = NULL ;
210
215
}
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 */
212
222
intern -> fptr_count = zend_hash_find_ptr (& class_type -> function_table , ZSTR_KNOWN (ZEND_STR_COUNT ));
213
223
if (intern -> fptr_count -> common .scope == parent ) {
214
224
intern -> fptr_count = NULL ;
@@ -460,7 +470,7 @@ static uint32_t spl_array_set_refcount(bool is_child, HashTable *ht, uint32_t re
460
470
return old_refcount ;
461
471
} /* }}} */
462
472
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 ) /* {{{ */
464
474
{
465
475
spl_array_object * intern = spl_array_from_obj (object );
466
476
HashTable * ht ;
@@ -474,6 +484,20 @@ static void spl_array_write_dimension_ex(int check_inherited, zend_object *objec
474
484
475
485
/* We are appending */
476
486
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
+
477
501
/* Cannot append if backing value is an object */
478
502
if (spl_array_is_object (intern )) {
479
503
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
491
515
return ;
492
516
}
493
517
518
+ /* offsetSet() method is overridden, so call it */
494
519
if (check_inherited && intern -> fptr_offset_set ) {
495
520
zend_call_method_with_2_params (object , object -> ce , & intern -> fptr_offset_set , "offsetSet" , NULL , offset , value );
496
521
return ;
@@ -542,7 +567,7 @@ static void spl_array_write_dimension_ex(int check_inherited, zend_object *objec
542
567
543
568
static void spl_array_write_dimension (zend_object * object , zval * offset , zval * value ) /* {{{ */
544
569
{
545
- spl_array_write_dimension_ex (1 , object , offset , value );
570
+ spl_array_write_dimension_ex (/* check_inherited */ true , object , offset , value );
546
571
} /* }}} */
547
572
548
573
static void spl_array_unset_dimension_ex (int check_inherited , zend_object * object , zval * offset ) /* {{{ */
@@ -703,9 +728,10 @@ PHP_METHOD(ArrayObject, offsetSet)
703
728
if (zend_parse_parameters (ZEND_NUM_ARGS (), "zz" , & index , & value ) == FAILURE ) {
704
729
RETURN_THROWS ();
705
730
}
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 );
707
732
} /* }}} */
708
733
734
+ /* Needed for spl_iterators.c:2938 */
709
735
void spl_array_iterator_append (zval * object , zval * append_value ) /* {{{ */
710
736
{
711
737
spl_array_write_dimension (Z_OBJ_P (object ), NULL , append_value );
@@ -719,7 +745,7 @@ PHP_METHOD(ArrayObject, append)
719
745
if (zend_parse_parameters (ZEND_NUM_ARGS (), "z" , & value ) == FAILURE ) {
720
746
RETURN_THROWS ();
721
747
}
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 );
723
749
} /* }}} */
724
750
725
751
/* {{{ Unsets the value at the specified $index. */
0 commit comments