summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinchen Hui <laruence@gmail.com>2015-11-23 06:12:03 -0800
committerAnatol Belski <ab@php.net>2015-11-24 20:38:42 +0100
commit067f3125a6c3fd01cde278bbd098253625715df3 (patch)
tree1165e760f669837832dc815664b3fa710f96c2e5
parentd749cd9b04d1bac1943ec17f078a8a87139c8d5d (diff)
downloadphp-git-067f3125a6c3fd01cde278bbd098253625715df3.tar.gz
Improved fix for bug (count on symbol table)
-rw-r--r--Zend/zend_hash.c36
-rw-r--r--Zend/zend_hash.h1
-rw-r--r--ext/standard/array.c41
-rw-r--r--ext/standard/var.c63
4 files changed, 48 insertions, 93 deletions
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index c324f1dfa8..283ceb8c18 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -283,6 +283,40 @@ ZEND_API void ZEND_FASTCALL zend_hash_extend(HashTable *ht, uint32_t nSize, zend
}
}
+static uint32_t zend_array_recalc_elements(HashTable *ht)
+{
+ zval *val;
+ uint32_t num = ht->nNumOfElements;
+
+ ZEND_HASH_FOREACH_VAL(ht, val) {
+ if (Z_TYPE_P(val) == IS_UNDEF) continue;
+ if (Z_TYPE_P(val) == IS_INDIRECT) {
+ if (UNEXPECTED(Z_TYPE_P(Z_INDIRECT_P(val)) == IS_UNDEF)) {
+ num--;
+ }
+ }
+ } ZEND_HASH_FOREACH_END();
+ return num;
+}
+/* }}} */
+
+ZEND_API uint32_t zend_array_count(HashTable *ht)
+{
+ uint32_t num;
+ if (UNEXPECTED(ht->u.v.flags & HASH_FLAG_HAS_EMPTY_IND)) {
+ num = zend_array_recalc_elements(ht);
+ if (UNEXPECTED(ht->nNumOfElements == num)) {
+ ht->u.v.flags &= ~HASH_FLAG_HAS_EMPTY_IND;
+ }
+ } else if (UNEXPECTED(ht == &EG(symbol_table))) {
+ num = zend_array_recalc_elements(ht);
+ } else {
+ num = zend_hash_num_elements(ht);
+ }
+ return num;
+}
+/* }}} */
+
ZEND_API void ZEND_FASTCALL zend_hash_set_apply_protection(HashTable *ht, zend_bool bApplyProtection)
{
if (bApplyProtection) {
@@ -1056,6 +1090,7 @@ ZEND_API int ZEND_FASTCALL zend_hash_del_ind(HashTable *ht, zend_string *key)
} else {
ZVAL_UNDEF(data);
}
+ ht->u.v.flags |= HASH_FLAG_HAS_EMPTY_IND;
}
} else {
_zend_hash_del_el_ex(ht, idx, p, prev);
@@ -1099,6 +1134,7 @@ ZEND_API int ZEND_FASTCALL zend_hash_str_del_ind(HashTable *ht, const char *str,
ht->pDestructor(data);
}
ZVAL_UNDEF(data);
+ ht->u.v.flags |= HASH_FLAG_HAS_EMPTY_IND;
}
} else {
_zend_hash_del_el_ex(ht, idx, p, prev);
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index 6ce37a909b..9fe99ac919 100644
--- a/Zend/zend_hash.h
+++ b/Zend/zend_hash.h
@@ -216,6 +216,7 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, compare_func_
ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht);
+ZEND_API uint32_t zend_array_count(HashTable *ht);
ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source);
ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht);
ZEND_API void ZEND_FASTCALL zend_symtable_clean(HashTable *ht);
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 6fec47545d..76fa073f40 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -757,41 +757,6 @@ PHP_FUNCTION(ksort)
}
/* }}} */
-static uint32_t php_array_recalc_elements(HashTable *ht) /* {{{ */
-{
- zval *val;
- uint32_t num = ht->nNumOfElements;
-
- ZEND_HASH_FOREACH_VAL(ht, val) {
- if (Z_TYPE_P(val) == IS_UNDEF) continue;
- if (Z_TYPE_P(val) == IS_INDIRECT) {
- if (Z_TYPE_P(Z_INDIRECT_P(val)) == IS_UNDEF) {
- num--;
- }
- }
- } ZEND_HASH_FOREACH_END();
- return num;
-}
-/* }}} */
-
-static uint32_t php_array_num_elements(zval *arr) /* {{{ */
-{
- uint32_t num;
- HashTable *ht = Z_ARRVAL_P(arr);
- if (UNEXPECTED(Z_SYMBOLTABLE_P(arr))) {
- num = php_array_recalc_elements(ht);
- } else if (UNEXPECTED(ht->u.v.flags & HASH_FLAG_HAS_EMPTY_IND)) {
- num = php_array_recalc_elements(ht);
- if (UNEXPECTED(ht->nNumOfElements == num)) {
- ht->u.v.flags &= ~HASH_FLAG_HAS_EMPTY_IND;
- }
- } else {
- num = zend_hash_num_elements(ht);
- }
- return num;
-}
-/* }}} */
-
PHPAPI zend_long php_count_recursive(zval *array, zend_long mode) /* {{{ */
{
zend_long cnt = 0;
@@ -803,7 +768,7 @@ PHPAPI zend_long php_count_recursive(zval *array, zend_long mode) /* {{{ */
return 0;
}
- cnt = php_array_num_elements(array);
+ cnt = zend_array_count(Z_ARRVAL_P(array));
if (mode == COUNT_RECURSIVE) {
if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(array))) {
Z_ARRVAL_P(array)->u.v.nApplyCount++;
@@ -848,7 +813,7 @@ PHP_FUNCTION(count)
RETURN_LONG(0);
break;
case IS_ARRAY:
- cnt = php_array_num_elements(array);
+ cnt = zend_array_count(Z_ARRVAL_P(array));
if (mode == COUNT_RECURSIVE) {
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(array), element) {
ZVAL_DEREF(element);
@@ -5193,7 +5158,7 @@ PHP_FUNCTION(array_filter)
}
}
- ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_key, string_key, operand) {
+ ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_key, string_key, operand) {
if (have_callback) {
if (use_type) {
/* Set up the key */
diff --git a/ext/standard/var.c b/ext/standard/var.c
index 72b2dd5ed5..7ae9fcf105 100644
--- a/ext/standard/var.c
+++ b/ext/standard/var.c
@@ -35,37 +35,6 @@
#define COMMON (is_ref ? "&" : "")
/* }}} */
-static uint32_t php_array_recalc_elements(HashTable *ht) /* {{{ */
-{
- zval *val;
- uint32_t num = ht->nNumOfElements;
-
- ZEND_HASH_FOREACH_VAL(ht, val) {
- if (Z_TYPE_P(val) == IS_UNDEF) continue;
- if (Z_TYPE_P(val) == IS_INDIRECT) {
- if (Z_TYPE_P(Z_INDIRECT_P(val)) == IS_UNDEF) {
- num--;
- }
- }
- } ZEND_HASH_FOREACH_END();
- return num;
-}
-/* }}} */
-
-static uint32_t php_array_num_elements(HashTable *ht) /* {{{ */
-{
- uint32_t num = ht->nNumOfElements;
-
- if (UNEXPECTED(ht->u.v.flags & HASH_FLAG_HAS_EMPTY_IND)) {
- num = php_array_recalc_elements(ht);
- if (UNEXPECTED(ht->nNumOfElements == num)) {
- ht->u.v.flags &= ~HASH_FLAG_HAS_EMPTY_IND;
- }
- }
- return num;
-}
-/* }}} */
-
static void php_array_element_dump(zval *zv, zend_ulong index, zend_string *key, int level) /* {{{ */
{
if (key == NULL) { /* numeric key */
@@ -150,11 +119,7 @@ again:
--myht->u.v.nApplyCount;
return;
}
- if (UNEXPECTED(Z_SYMBOLTABLE_P(struc))) {
- count = php_array_recalc_elements(myht);
- } else {
- count = php_array_num_elements(myht);
- }
+ count = zend_array_count(myht);
php_printf("%sarray(%d) {\n", COMMON, count);
is_temp = 0;
@@ -182,7 +147,7 @@ again:
myht = Z_OBJDEBUG_P(struc, is_temp);
class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc));
- php_printf("%sobject(%s)#%d (%d) {\n", COMMON, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? php_array_num_elements(myht) : 0);
+ php_printf("%sobject(%s)#%d (%d) {\n", COMMON, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? zend_array_count(myht) : 0);
zend_string_release(class_name);
if (myht) {
@@ -324,11 +289,7 @@ again:
PUTS("*RECURSION*\n");
return;
}
- if (UNEXPECTED(Z_SYMBOLTABLE_P(struc))) {
- count = php_array_recalc_elements(myht);
- } else {
- count = php_array_num_elements(myht);
- }
+ count = zend_array_count(myht);
php_printf("%sarray(%d) refcount(%u){\n", COMMON, count, Z_REFCOUNTED_P(struc) ? Z_REFCOUNT_P(struc) : 1);
ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, val) {
zval_array_element_dump(val, index, key, level);
@@ -356,7 +317,7 @@ again:
}
}
class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc));
- php_printf("%sobject(%s)#%d (%d) refcount(%u){\n", COMMON, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? php_array_num_elements(myht) : 0, Z_REFCOUNT_P(struc));
+ php_printf("%sobject(%s)#%d (%d) refcount(%u){\n", COMMON, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? zend_array_count(myht) : 0, Z_REFCOUNT_P(struc));
zend_string_release(class_name);
if (myht) {
ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, val) {
@@ -707,14 +668,10 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_pt
* changes the count if the variable is incomplete class */
if (Z_TYPE_P(retval_ptr) == IS_ARRAY) {
ht = Z_ARRVAL_P(retval_ptr);
- if (UNEXPECTED(Z_SYMBOLTABLE_P(struc))) {
- count = php_array_recalc_elements(ht);
- } else {
- count = php_array_num_elements(ht);
- }
+ count = zend_array_count(ht);
} else if (Z_TYPE_P(retval_ptr) == IS_OBJECT) {
ht = Z_OBJPROP_P(retval_ptr);
- count = php_array_num_elements(ht);
+ count = zend_array_count(ht);
if (incomplete_class) {
--count;
}
@@ -935,17 +892,13 @@ again:
if (Z_TYPE_P(struc) == IS_ARRAY) {
smart_str_appendl(buf, "a:", 2);
myht = Z_ARRVAL_P(struc);
- if (UNEXPECTED(Z_SYMBOLTABLE_P(struc))) {
- i = php_array_recalc_elements(myht);
- } else {
- i = php_array_num_elements(myht);
- }
+ i = zend_array_count(myht);
} else {
incomplete_class = php_var_serialize_class_name(buf, struc);
myht = Z_OBJPROP_P(struc);
/* count after serializing name, since php_var_serialize_class_name
* changes the count if the variable is incomplete class */
- i = php_array_num_elements(myht);
+ i = zend_array_count(myht);
if (i > 0 && incomplete_class) {
--i;
}