diff options
Diffstat (limited to 'ext/standard/var_unserializer.re')
-rw-r--r-- | ext/standard/var_unserializer.re | 159 |
1 files changed, 84 insertions, 75 deletions
diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 0b0917a60a..81cc26db9d 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 7 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2015 The PHP Group | + | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -42,7 +42,7 @@ static inline void var_push(php_unserialize_data_t *var_hashx, zval *rval) { var_entries *var_hash = (*var_hashx)->last; #if VAR_ENTRIES_DBG - fprintf(stderr, "var_push(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval)); + fprintf(stderr, "var_push(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_P(rval)); #endif if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) { @@ -64,69 +64,45 @@ static inline void var_push(php_unserialize_data_t *var_hashx, zval *rval) PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval *rval) { - var_dtor_entries *var_hash; - - if (!var_hashx || !*var_hashx) { - return; - } - - var_hash = (*var_hashx)->last_dtor; -#if VAR_ENTRIES_DBG - fprintf(stderr, "var_push_dtor(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval)); -#endif - - if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) { - var_hash = emalloc(sizeof(var_dtor_entries)); - var_hash->used_slots = 0; - var_hash->next = 0; - - if (!(*var_hashx)->first_dtor) { - (*var_hashx)->first_dtor = var_hash; - } else { - ((var_dtor_entries *) (*var_hashx)->last_dtor)->next = var_hash; - } - - (*var_hashx)->last_dtor = var_hash; - } - - ZVAL_COPY(&var_hash->data[var_hash->used_slots], rval); - var_hash->used_slots++; + zval *tmp_var = var_tmp_var(var_hashx); + if (!tmp_var) { + return; + } + ZVAL_COPY(tmp_var, rval); } -//??? -#if 0 -PHPAPI void var_push_dtor_no_addref(php_unserialize_data_t *var_hashx, zval *rval) +PHPAPI zval *var_tmp_var(php_unserialize_data_t *var_hashx) { - var_dtor_entries *var_hash = (*var_hashx)->last_dtor; -#if VAR_ENTRIES_DBG - fprintf(stderr, "var_push_dtor_no_addref(%ld): %d (%d)\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval), Z_REFCOUNT_PP(rval)); -#endif - - if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) { - var_hash = emalloc(sizeof(var_dtor_entries)); - var_hash->used_slots = 0; - var_hash->next = 0; - - if (!(*var_hashx)->first_dtor) { - (*var_hashx)->first_dtor = var_hash; - } else { - ((var_entries *) (*var_hashx)->last_dtor)->next = var_hash; - } - - (*var_hashx)->last_dtor = var_hash; - } - - ZVAL_COPY_VALUE(&var_hash->data[var_hash->used_slots], rval); - var_hash->used_slots++; + var_dtor_entries *var_hash; + + if (!var_hashx || !*var_hashx) { + return NULL; + } + + var_hash = (*var_hashx)->last_dtor; + if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) { + var_hash = emalloc(sizeof(var_dtor_entries)); + var_hash->used_slots = 0; + var_hash->next = 0; + + if (!(*var_hashx)->first_dtor) { + (*var_hashx)->first_dtor = var_hash; + } else { + ((var_dtor_entries *) (*var_hashx)->last_dtor)->next = var_hash; + } + + (*var_hashx)->last_dtor = var_hash; + } + ZVAL_UNDEF(&var_hash->data[var_hash->used_slots]); + return &var_hash->data[var_hash->used_slots++]; } -#endif PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval *nzval) { zend_long i; var_entries *var_hash = (*var_hashx)->first; #if VAR_ENTRIES_DBG - fprintf(stderr, "var_replace(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(nzval)); + fprintf(stderr, "var_replace(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_P(nzval)); #endif while (var_hash) { @@ -171,16 +147,19 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) while (var_hash) { next = var_hash->next; - efree(var_hash); + efree_size(var_hash, sizeof(var_entries)); var_hash = next; } while (var_dtor_hash) { for (i = 0; i < var_dtor_hash->used_slots; i++) { +#if VAR_ENTRIES_DBG + fprintf(stderr, "var_destroy dtor(%p, %ld)\n", var_dtor_hash->data[i], Z_REFCOUNT_P(var_dtor_hash->data[i])); +#endif zval_ptr_dtor(&var_dtor_hash->data[i]); } next = var_dtor_hash->next; - efree(var_dtor_hash); + efree_size(var_dtor_hash, sizeof(var_dtor_entries)); var_dtor_hash = next; } } @@ -190,7 +169,7 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) static zend_string *unserialize_str(const unsigned char **p, size_t len, size_t maxlen) { size_t i, j; - zend_string *str = zend_string_alloc(len, 0); + zend_string *str = zend_string_safe_alloc(1, len, 0, 0); unsigned char *end = *(unsigned char **)p+maxlen; if (end < *p) { @@ -390,13 +369,22 @@ string_key: } } - zval_dtor(&key); - if (!php_var_unserialize_ex(data, p, max, var_hash, classes)) { + zval_dtor(&key); return 0; } - var_push_dtor(var_hash, data); + if (UNEXPECTED(Z_ISUNDEF_P(data))) { + if (Z_TYPE(key) == IS_LONG) { + zend_hash_index_del(ht, Z_LVAL(key)); + } else { + zend_hash_del_ind(ht, Z_STR(key)); + } + } else { + var_push_dtor(var_hash, data); + } + + zval_dtor(&key); if (elements && *(*p-1) != ';' && *(*p-1) != '}') { (*p)--; @@ -470,13 +458,15 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements) { zval retval; zval fname; + HashTable *ht; if (Z_TYPE_P(rval) != IS_OBJECT) { return 0; } - //??? TODO: resize before - if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_P(rval), elements, 1)) { + ht = Z_OBJPROP_P(rval); + zend_hash_extend(ht, zend_hash_num_elements(ht) + elements, (ht->u.flags & HASH_FLAG_PACKED)); + if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) { return 0; } @@ -541,6 +531,10 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER) } zval_ptr_dtor(rval); + if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) { + ZVAL_UNDEF(rval); + return 1; + } if (Z_ISREF_P(rval_ref)) { ZVAL_COPY(rval, rval_ref); } else { @@ -562,14 +556,16 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER) return 0; } -//??? -//??? if (rval == rval_ref) return 0; + if (rval_ref == rval) { + return 0; + } + + if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) { + ZVAL_UNDEF(rval); + return 1; + } -//??? if (!ZVAL_IS_UNDEF(rval)) { -//??? var_push_dtor_no_addref(var_hash, rval); -//??? } ZVAL_COPY(rval, rval_ref); -//??? Z_UNSET_ISREF_PP(rval); return 1; } @@ -657,6 +653,11 @@ use_double: return 0; } + if (*(YYCURSOR + 1) != ';') { + *p = YYCURSOR + 1; + return 0; + } + YYCURSOR += 2; *p = YYCURSOR; @@ -685,6 +686,12 @@ use_double: return 0; } + if (*(YYCURSOR + 1) != ';') { + efree(str); + *p = YYCURSOR + 1; + return 0; + } + YYCURSOR += 2; *p = YYCURSOR; @@ -696,15 +703,18 @@ use_double: zend_long elements = parse_iv(start + 2); /* use iv() not uiv() in order to check data range */ *p = YYCURSOR; + if (!var_hash) return 0; if (elements < 0) { return 0; } array_init_size(rval, elements); -//??? we can't convert from packed to hash during unserialization, because -//??? reference to some zvals might be keept in var_hash (to support references) - zend_hash_real_init(Z_ARRVAL_P(rval), 0); + if (elements) { + /* we can't convert from packed to hash during unserialization, because + reference to some zvals might be keept in var_hash (to support references) */ + zend_hash_real_init(Z_ARRVAL_P(rval), 0); + } if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_P(rval), elements, 0)) { return 0; @@ -714,8 +724,7 @@ use_double: } "o:" iv ":" ["] { - -//??? INIT_PZVAL(rval); + if (!var_hash) return 0; return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); @@ -735,11 +744,11 @@ object ":" uiv ":" ["] { zval retval; zval args[1]; + if (!var_hash) return 0; if (*start == 'C') { custom_object = 1; } -//??? INIT_PZVAL(rval); len2 = len = parse_uiv(start + 2); maxlen = max - YYCURSOR; if (maxlen < len || len == 0) { |