diff options
Diffstat (limited to 'ext/spl/spl_array.c')
-rw-r--r-- | ext/spl/spl_array.c | 38 |
1 files changed, 22 insertions, 16 deletions
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 3e97e9448d..c631c187c9 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -402,7 +402,7 @@ static zval *spl_array_read_dimension_ex(int check_inherited, zval *object, zval /* When in a write context, * ZE has to be fooled into thinking this is in a reference set * by separating (if necessary) and returning as an is_ref=1 zval (even if refcount == 1) */ - if ((type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) && !Z_ISREF_PP(ret)) { + if ((type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) && !Z_ISREF_PP(ret) && ret != &EG(uninitialized_zval_ptr)) { if (Z_REFCOUNT_PP(ret) > 1) { zval *newval; @@ -603,7 +603,7 @@ static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *o if (rv && zend_is_true(rv TSRMLS_CC)) { zval_ptr_dtor(&rv); - if (check_empty == 2) { + if (check_empty != 1) { return 1; } else if (intern->fptr_offset_get) { value = spl_array_read_dimension_ex(1, object, offset, BP_VAR_R TSRMLS_CC); @@ -629,6 +629,7 @@ static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *o return 0; } break; + case IS_DOUBLE: case IS_RESOURCE: case IS_BOOL: @@ -646,28 +647,20 @@ static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *o return 0; } break; + default: zend_error(E_WARNING, "Illegal offset type"); return 0; } - if (check_inherited && intern->fptr_offset_get) { + if (check_empty && check_inherited && intern->fptr_offset_get) { value = spl_array_read_dimension_ex(1, object, offset, BP_VAR_R TSRMLS_CC); } else { value = *tmp; } } - switch (check_empty) { - case 0: - return Z_TYPE_P(value) != IS_NULL; - case 2: - return 1; - case 1: - return zend_is_true(value TSRMLS_CC); - } - - return 0; + return check_empty ? zend_is_true(value TSRMLS_CC) : Z_TYPE_P(value) != IS_NULL; } /* }}} */ static int spl_array_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC) /* {{{ */ @@ -938,7 +931,14 @@ static int spl_array_skip_protected(spl_array_object *intern, HashTable *aht TSR if (Z_TYPE_P(intern->array) == IS_OBJECT) { do { if (zend_hash_get_current_key_ex(aht, &string_key, &string_length, &num_key, 0, &intern->pos) == HASH_KEY_IS_STRING) { - if (!string_length || string_key[0]) { + /* zend_hash_get_current_key_ex() should never set + * string_length to 0 when returning HASH_KEY_IS_STRING, but we + * may as well be defensive and consider that successful. + * Beyond that, we're looking for protected keys (which will + * have a null byte at string_key[0]), but want to avoid + * skipping completely empty keys (which will also have the + * null byte, but a string_length of 1). */ + if (!string_length || string_key[0] || string_length == 1) { return SUCCESS; } } else { @@ -1742,6 +1742,7 @@ SPL_METHOD(Array, unserialize) const unsigned char *p, *s; php_unserialize_data_t var_hash; zval *pmembers, *pflags = NULL; + HashTable *aht; long flags; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) { @@ -1749,7 +1750,12 @@ SPL_METHOD(Array, unserialize) } if (buf_len == 0) { - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Empty serialized string cannot be empty"); + return; + } + + aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + if (aht->nApplyCount > 0) { + zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); return; } @@ -1805,7 +1811,7 @@ SPL_METHOD(Array, unserialize) ++p; ALLOC_INIT_ZVAL(pmembers); - if (!php_var_unserialize(&pmembers, &p, s + buf_len, &var_hash TSRMLS_CC)) { + if (!php_var_unserialize(&pmembers, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pmembers) != IS_ARRAY) { zval_ptr_dtor(&pmembers); goto outexcept; } |