From bb4b50636c86b8a2994a7d1e3c1925aa86146760 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 1 Sep 2015 10:39:00 +0300 Subject: [PATCH 1/2] Fixed one more problem related to bug #70187 (Notice: unserialize(): Unexpected end of serialized data) --- Zend/tests/bug70187_2.phpt | 11 ++++++++ ext/standard/var.c | 57 ++++++++++++++++++++++++++++---------- 2 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 Zend/tests/bug70187_2.phpt diff --git a/Zend/tests/bug70187_2.phpt b/Zend/tests/bug70187_2.phpt new file mode 100644 index 00000000000..76a0b600634 --- /dev/null +++ b/Zend/tests/bug70187_2.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug #70187 (Notice: unserialize(): Unexpected end of serialized data) +--FILE-- + +--EXPECT-- +ok diff --git a/ext/standard/var.c b/ext/standard/var.c index ddd82ffa75b..40b5acb0412 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -35,21 +35,28 @@ #define COMMON (is_ref ? "&" : "") /* }}} */ +static uint32_t zend_hash_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 zend_obj_num_elements(HashTable *ht) /* {{{ */ { - uint num = ht->nNumOfElements; + uint32_t num = ht->nNumOfElements; if (UNEXPECTED(ht->u.v.flags & HASH_FLAG_HAS_EMPTY_IND)) { - zval *val; - - 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(); + num = zend_hash_recalc_elements(ht); if (UNEXPECTED(ht->nNumOfElements == num)) { ht->u.v.flags &= ~HASH_FLAG_HAS_EMPTY_IND; } @@ -107,6 +114,7 @@ PHPAPI void php_var_dump(zval *struc, int level) /* {{{ */ zend_ulong num; zend_string *key; zval *val; + uint32_t count; if (level > 1) { php_printf("%*c", level - 1, ' '); @@ -141,7 +149,12 @@ again: --myht->u.v.nApplyCount; return; } - php_printf("%sarray(%d) {\n", COMMON, zend_hash_num_elements(myht)); + if (UNEXPECTED(Z_SYMBOLTABLE_P(struc))) { + count = zend_hash_recalc_elements(myht); + } else { + count = zend_hash_num_elements(myht); + } + php_printf("%sarray(%d) {\n", COMMON, count); is_temp = 0; ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) { @@ -275,6 +288,7 @@ PHPAPI void php_debug_zval_dump(zval *struc, int level) /* {{{ */ zend_ulong index; zend_string *key; zval *val; + uint32_t count; if (level > 1) { php_printf("%*c", level - 1, ' '); @@ -309,7 +323,12 @@ again: PUTS("*RECURSION*\n"); return; } - php_printf("%sarray(%d) refcount(%u){\n", COMMON, zend_hash_num_elements(myht), Z_REFCOUNTED_P(struc) ? Z_REFCOUNT_P(struc) : 1); + if (UNEXPECTED(Z_SYMBOLTABLE_P(struc))) { + count = zend_hash_recalc_elements(myht); + } else { + count = zend_hash_num_elements(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); } ZEND_HASH_FOREACH_END(); @@ -688,7 +707,11 @@ 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); - count = zend_hash_num_elements(ht); + if (UNEXPECTED(Z_SYMBOLTABLE_P(struc))) { + count = zend_hash_recalc_elements(ht); + } else { + count = zend_hash_num_elements(ht); + } } else if (Z_TYPE_P(retval_ptr) == IS_OBJECT) { ht = Z_OBJPROP_P(retval_ptr); count = zend_obj_num_elements(ht); @@ -912,7 +935,11 @@ again: if (Z_TYPE_P(struc) == IS_ARRAY) { smart_str_appendl(buf, "a:", 2); myht = Z_ARRVAL_P(struc); - i = zend_hash_num_elements(myht); + if (UNEXPECTED(Z_SYMBOLTABLE_P(struc))) { + i = zend_hash_recalc_elements(myht); + } else { + i = zend_hash_num_elements(myht); + } } else { incomplete_class = php_var_serialize_class_name(buf, struc); myht = Z_OBJPROP_P(struc); From d8eee72a840ef7e86c5f9cc0481a23f373daf96c Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 1 Sep 2015 12:56:33 +0300 Subject: [PATCH 2/2] Fixed possible caching with invalid key value --- ext/opcache/ZendAccelerator.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 01e9eca28f6..905700e53b3 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -917,13 +917,16 @@ char *accel_make_persistent_key(const char *path, int path_length, int *key_len) /* CWD and include_path don't matter for absolute file names and streams */ if (IS_ABSOLUTE_PATH(path, path_length)) { /* pass */ + ZCG(key_len) = 0; } else if (UNEXPECTED(is_stream_path(path))) { if (!is_cacheable_stream_path(path)) { return NULL; } /* pass */ + ZCG(key_len) = 0; } else if (UNEXPECTED(!ZCG(accel_directives).use_cwd)) { /* pass */ + ZCG(key_len) = 0; } else { const char *include_path = NULL, *cwd = NULL; int include_path_len = 0, cwd_len = 0;