From: Nikita Popov Date: Wed, 24 Feb 2016 16:18:07 +0000 (+0100) Subject: Don't use ht applyCount for AO sorting protection X-Git-Tag: php-7.0.5RC1~66 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ea02f5765608c13cb92b5b7879878b981c99b33e;p=php Don't use ht applyCount for AO sorting protection 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. --- diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 366617f91b..9ddd38bccf 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -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(¶ms[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(¶ms[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 index 0000000000..0fb128b655 --- /dev/null +++ b/ext/spl/tests/ArrayObject_dump_during_sort.phpt @@ -0,0 +1,27 @@ +--TEST-- +Dumping an ArrayObject while it is being sorted +--FILE-- +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) + } +}