]> granicus.if.org Git - php/commitdiff
Don't use ht applyCount for AO sorting protection
authorNikita Popov <nikic@php.net>
Wed, 24 Feb 2016 16:18:07 +0000 (17:18 +0100)
committerNikita Popov <nikic@php.net>
Wed, 24 Feb 2016 16:18:07 +0000 (17:18 +0100)
Instead use the AOs own applyCount that just got freed up. Using the
apply count of the HashTable has various side effects, e.g. preventing
the ArrayObject from being dumped.

ext/spl/spl_array.c
ext/spl/tests/ArrayObject_dump_during_sort.phpt [new file with mode: 0644]

index 366617f91bcf2418104d11ee06a6d6d186b71f6c..9ddd38bccfef19c2d21d63e6e2ffbcea8128673e 100644 (file)
@@ -275,7 +275,7 @@ static zval *spl_array_get_dimension_ptr(int check_inherited, zval *object, zval
                return &EG(uninitialized_zval);
        }
 
-       if ((type == BP_VAR_W || type == BP_VAR_RW) && (ht->u.v.nApplyCount > 0)) {
+       if ((type == BP_VAR_W || type == BP_VAR_RW) && intern->nApplyCount > 0) {
                zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
                return &EG(error_zval);
        }
@@ -434,12 +434,13 @@ static void spl_array_write_dimension_ex(int check_inherited, zval *object, zval
                return;
        }
 
+       if (intern->nApplyCount > 0) {
+               zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+               return;
+       }
+
        if (!offset) {
                ht = spl_array_get_hash_table(intern);
-               if (ht->u.v.nApplyCount > 0) {
-                       zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
-                       return;
-               }
                if (Z_REFCOUNTED_P(value)) {
                        Z_ADDREF_P(value);
                }
@@ -455,10 +456,6 @@ try_again:
        switch (Z_TYPE_P(offset)) {
                case IS_STRING:
                        ht = spl_array_get_hash_table(intern);
-                       if (ht->u.v.nApplyCount > 0) {
-                               zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
-                               return;
-                       }
                        zend_symtable_update_ind(ht, Z_STR_P(offset), value);
                        return;
                case IS_DOUBLE:
@@ -477,18 +474,10 @@ try_again:
                        index = Z_LVAL_P(offset);
 num_index:
                        ht = spl_array_get_hash_table(intern);
-                       if (ht->u.v.nApplyCount > 0) {
-                               zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
-                               return;
-                       }
                        zend_hash_index_update(ht, index, value);
                        return;
                case IS_NULL:
                        ht = spl_array_get_hash_table(intern);
-                       if (ht->u.v.nApplyCount > 0) {
-                               zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
-                               return;
-                       }
                        zend_hash_next_index_insert(ht, value);
                        return;
                case IS_REFERENCE:
@@ -518,14 +507,15 @@ static void spl_array_unset_dimension_ex(int check_inherited, zval *object, zval
                return;
        }
 
+       if (intern->nApplyCount > 0) {
+               zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+               return;
+       }
+
 try_again:
        switch (Z_TYPE_P(offset)) {
        case IS_STRING:
                ht = spl_array_get_hash_table(intern);
-               if (ht->u.v.nApplyCount > 0) {
-                       zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
-                       return;
-               }
                if (ht == &EG(symbol_table)) {
                        if (zend_delete_global_variable(Z_STR_P(offset))) {
                                zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset));
@@ -571,10 +561,6 @@ try_again:
                index = Z_LVAL_P(offset);
 num_index:
                ht = spl_array_get_hash_table(intern);
-               if (ht->u.v.nApplyCount > 0) {
-                       zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
-                       return;
-               }
                if (zend_hash_index_del(ht, index) == FAILURE) {
                        zend_error(E_NOTICE,"Undefined offset: %pd", index);
                }
@@ -1439,9 +1425,9 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam
        ZVAL_ARR(Z_REFVAL(params[0]), aht);
 
        if (!use_arg) {
-               aht->u.v.nApplyCount++;
+               intern->nApplyCount++;
                call_user_function_ex(EG(function_table), NULL, &function_name, return_value, 1, params, 1, NULL);
-               aht->u.v.nApplyCount--;
+               intern->nApplyCount--;
        } else if (use_arg == SPL_ARRAY_METHOD_MAY_USER_ARG) {
                if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "|z", &arg) == FAILURE) {
                        zend_throw_exception(spl_ce_BadMethodCallException, "Function expects one argument at most", 0);
@@ -1450,18 +1436,18 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam
                if (arg) {
                        ZVAL_COPY_VALUE(&params[1], arg);
                }
-               aht->u.v.nApplyCount++;
+               intern->nApplyCount++;
                call_user_function_ex(EG(function_table), NULL, &function_name, return_value, arg ? 2 : 1, params, 1, NULL);
-               aht->u.v.nApplyCount--;
+               intern->nApplyCount--;
        } else {
                if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "z", &arg) == FAILURE) {
                        zend_throw_exception(spl_ce_BadMethodCallException, "Function expects exactly one argument", 0);
                        goto exit;
                }
                ZVAL_COPY_VALUE(&params[1], arg);
-               aht->u.v.nApplyCount++;
+               intern->nApplyCount++;
                call_user_function_ex(EG(function_table), NULL, &function_name, return_value, 2, params, 1, NULL);
-               aht->u.v.nApplyCount--;
+               intern->nApplyCount--;
        }
 
 exit:
@@ -1727,7 +1713,6 @@ SPL_METHOD(Array, unserialize)
        const unsigned char *p, *s;
        php_unserialize_data_t var_hash;
        zval *members, *zflags;
-       HashTable *aht;
        zend_long flags;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &buf, &buf_len) == FAILURE) {
@@ -1738,8 +1723,7 @@ SPL_METHOD(Array, unserialize)
                return;
        }
 
-       aht = spl_array_get_hash_table(intern);
-       if (aht->u.v.nApplyCount > 0) {
+       if (intern->nApplyCount > 0) {
                zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
                return;
        }
diff --git a/ext/spl/tests/ArrayObject_dump_during_sort.phpt b/ext/spl/tests/ArrayObject_dump_during_sort.phpt
new file mode 100644 (file)
index 0000000..0fb128b
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--
+Dumping an ArrayObject while it is being sorted
+--FILE--
+<?php
+
+$ao = new ArrayObject([1, 2, 3]);
+$i = 0;
+$ao->uasort(function($a, $b) use ($ao, &$i) {
+    if ($i++ == 0) {
+        var_dump($ao);
+    }
+    return $a <=> $b;
+});
+
+?>
+--EXPECT--
+object(ArrayObject)#1 (1) {
+  ["storage":"ArrayObject":private]=>
+  array(3) {
+    [0]=>
+    int(1)
+    [1]=>
+    int(2)
+    [2]=>
+    int(3)
+  }
+}