diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 6679cb1e467..ba089674c1b 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -423,41 +423,19 @@ ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_inf } /* }}} */ -static zend_long *zend_get_property_guard(zend_object *zobj, zend_property_info *property_info, zval *member) /* {{{ */ +static zend_long *zend_get_property_guard(zend_object *zobj, zval *member) /* {{{ */ { - zend_property_info info; zval stub, *guard; - zend_string *str = NULL; - if (!property_info) { - property_info = &info; - info.name = Z_STR_P(member); - } else if(property_info->name->val[0] == '\0'){ - const char *class_name = NULL, *prop_name = NULL; - size_t prop_name_len; - zend_unmangle_property_name_ex(property_info->name, &class_name, - &prop_name, &prop_name_len); - if (class_name) { - /* use unmangled name for protected properties */ - str = info.name = zend_string_init(prop_name, prop_name_len, 0); - property_info = &info; - } - } if (!zobj->guards) { ALLOC_HASHTABLE(zobj->guards); zend_hash_init(zobj->guards, 8, NULL, NULL, 0); - } else if ((guard = zend_hash_find(zobj->guards, property_info->name)) != NULL) { - if (str) { - zend_string_release(str); - } + } else if ((guard = zend_hash_find(zobj->guards, Z_STR_P(member))) != NULL) { return &Z_LVAL_P(guard); } ZVAL_LONG(&stub, 0); - guard = zend_hash_add_new(zobj->guards, property_info->name, &stub); - if (str) { - zend_string_release(str); - } + guard = zend_hash_add_new(zobj->guards, Z_STR_P(member), &stub); return &Z_LVAL_P(guard); } /* }}} */ @@ -468,9 +446,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_ zval tmp_member; zval *retval; zend_property_info *property_info; - int silent; - silent = (type == BP_VAR_IS); zobj = Z_OBJ_P(object); ZVAL_UNDEF(&tmp_member); @@ -485,7 +461,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_ #endif /* make zend_get_property_info silent if we have getter - we may want to use it */ - property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), silent || (zobj->ce->__get != NULL), cache_slot TSRMLS_CC); + property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), (type == BP_VAR_IS) || (zobj->ce->__get != NULL), cache_slot TSRMLS_CC); if (EXPECTED(property_info != NULL)) { if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && @@ -502,7 +478,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_ /* magic get */ if (zobj->ce->__get) { - zend_long *guard = zend_get_property_guard(zobj, property_info, member); + zend_long *guard = zend_get_property_guard(zobj, member); if (!((*guard) & IN_GET)) { zval tmp_object; @@ -533,13 +509,13 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_ zend_error(E_ERROR, "Cannot access property started with '\\0'"); } } - if (!silent) { + if (type != BP_VAR_IS) { zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name->val, Z_STRVAL_P(member)); } retval = &EG(uninitialized_zval); } } else { - if (!silent) { + if ((type != BP_VAR_IS)) { zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name->val, Z_STRVAL_P(member)); } retval = &EG(uninitialized_zval); @@ -635,7 +611,7 @@ found: /* magic set */ if (zobj->ce->__set) { - zend_long *guard = zend_get_property_guard(zobj, property_info, member); + zend_long *guard = zend_get_property_guard(zobj, member); if (!((*guard) & IN_SET)) { zval tmp_object; @@ -809,7 +785,7 @@ static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type, } if (!zobj->ce->__get || - (guard = zend_get_property_guard(zobj, property_info, member)) == NULL || + (guard = zend_get_property_guard(zobj, member)) == NULL || (property_info && ((*guard) & IN_GET))) { ZVAL_NULL(&tmp); @@ -875,7 +851,7 @@ static void zend_std_unset_property(zval *object, zval *member, void **cache_slo /* magic unset */ if (zobj->ce->__unset) { - zend_long *guard = zend_get_property_guard(zobj, property_info, member); + zend_long *guard = zend_get_property_guard(zobj, member); if (!((*guard) & IN_UNSET)) { zval tmp_object; @@ -1483,7 +1459,7 @@ found: result = 0; if ((has_set_exists != 2) && zobj->ce->__isset) { - zend_long *guard = zend_get_property_guard(zobj, property_info, member); + zend_long *guard = zend_get_property_guard(zobj, member); if (!((*guard) & IN_ISSET)) { zval rv; diff --git a/ext/standard/array.c b/ext/standard/array.c index 7d8e4d0efe5..98a1c21b3ef 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1992,13 +1992,14 @@ PHP_FUNCTION(array_push) } /* }}} */ -/* {{{ void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end) */ -static void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end) +/* {{{ proto mixed array_pop(array stack) + Pops an element off the end of the array */ +PHP_FUNCTION(array_pop) { zval *stack, /* Input stack */ *val; /* Value to be popped */ - zend_string *key = NULL; - zend_ulong index; + uint32_t idx; + Bucket *p; #ifndef FAST_ZPP if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &stack) == FAILURE) { @@ -2014,56 +2015,118 @@ static void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end) return; } - /* Get the first or last value and copy it into the return value */ - if (off_the_end) { - zend_hash_internal_pointer_end(Z_ARRVAL_P(stack)); - while (1) { - val = zend_hash_get_current_data(Z_ARRVAL_P(stack)); - if (!val) { - return; - } else if (Z_TYPE_P(val) == IS_INDIRECT) { - val = Z_INDIRECT_P(val); - if (Z_TYPE_P(val) == IS_UNDEF) { - zend_hash_move_backwards(Z_ARRVAL_P(stack)); - continue; - } - } - break; + /* Get the last value and copy it into the return value */ + idx = Z_ARRVAL_P(stack)->nNumUsed; + while (1) { + if (idx == 0) { + return; } - } else { - zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack)); - while (1) { - val = zend_hash_get_current_data(Z_ARRVAL_P(stack)); - if (!val) { - return; - } else if (Z_TYPE_P(val) == IS_INDIRECT) { - val = Z_INDIRECT_P(val); - if (Z_TYPE_P(val) == IS_UNDEF) { - zend_hash_move_forward(Z_ARRVAL_P(stack)); - continue; - } - } + idx--; + p = Z_ARRVAL_P(stack)->arData + idx; + val = &p->val; + if (Z_TYPE_P(val) == IS_INDIRECT) { + val = Z_INDIRECT_P(val); + } + if (Z_TYPE_P(val) != IS_UNDEF) { break; } } - RETVAL_ZVAL_FAST(val); + ZVAL_DEREF(val); + ZVAL_COPY(return_value, val); - /* Delete the first or last value */ - zend_hash_get_current_key(Z_ARRVAL_P(stack), &key, &index, 0); - if (key && Z_ARRVAL_P(stack) == &EG(symbol_table).ht) { - zend_delete_global_variable(key TSRMLS_CC); - } else if (key) { - zend_hash_del(Z_ARRVAL_P(stack), key); - } else { - zend_hash_index_del(Z_ARRVAL_P(stack), index); + if (!p->key && Z_ARRVAL_P(stack)->nNextFreeElement > 0 && p->h >= (zend_ulong)(Z_ARRVAL_P(stack)->nNextFreeElement - 1)) { + Z_ARRVAL_P(stack)->nNextFreeElement = Z_ARRVAL_P(stack)->nNextFreeElement - 1; } - /* If we did a shift... re-index like it did before */ - if (!off_the_end) { - unsigned int k = 0; + /* Delete the last value */ + if (p->key) { + if (Z_ARRVAL_P(stack) == &EG(symbol_table).ht) { + zend_delete_global_variable(p->key TSRMLS_CC); + } else { + zend_hash_del(Z_ARRVAL_P(stack), p->key); + } + } else { + zend_hash_index_del(Z_ARRVAL_P(stack), p->h); + } + + zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack)); +} +/* }}} */ + +/* {{{ proto mixed array_shift(array stack) + Pops an element off the beginning of the array */ +PHP_FUNCTION(array_shift) +{ + zval *stack, /* Input stack */ + *val; /* Value to be popped */ + uint32_t idx; + Bucket *p; + +#ifndef FAST_ZPP + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &stack) == FAILURE) { + return; + } +#else + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY_EX(stack, 0, 1) + ZEND_PARSE_PARAMETERS_END(); +#endif + + if (zend_hash_num_elements(Z_ARRVAL_P(stack)) == 0) { + return; + } + + /* Get the first value and copy it into the return value */ + idx = 0; + while (1) { + if (idx == Z_ARRVAL_P(stack)->nNumUsed) { + return; + } + p = Z_ARRVAL_P(stack)->arData + idx; + val = &p->val; + if (Z_TYPE_P(val) == IS_INDIRECT) { + val = Z_INDIRECT_P(val); + } + if (Z_TYPE_P(val) != IS_UNDEF) { + break; + } + idx++; + } + ZVAL_DEREF(val); + ZVAL_COPY(return_value, val); + + /* Delete the first value */ + if (p->key) { + if (Z_ARRVAL_P(stack) == &EG(symbol_table).ht) { + zend_delete_global_variable(p->key TSRMLS_CC); + } else { + zend_hash_del(Z_ARRVAL_P(stack), p->key); + } + } else { + zend_hash_index_del(Z_ARRVAL_P(stack), p->h); + } + + /* re-index like it did before */ + if (Z_ARRVAL_P(stack)->u.flags & HASH_FLAG_PACKED) { + uint32_t k = 0; + + for (idx = 0; idx < Z_ARRVAL_P(stack)->nNumUsed; idx++) { + p = Z_ARRVAL_P(stack)->arData + idx; + if (Z_TYPE(p->val) == IS_UNDEF) continue; + if (idx != k) { + Bucket *q = Z_ARRVAL_P(stack)->arData + k; + q->h = k; + q->key = NULL; + ZVAL_COPY_VALUE(&q->val, &p->val); + ZVAL_UNDEF(&p->val); + } + k++; + } + Z_ARRVAL_P(stack)->nNumUsed = k; + Z_ARRVAL_P(stack)->nNextFreeElement = k; + } else { + uint32_t k = 0; int should_rehash = 0; - uint idx; - Bucket *p; for (idx = 0; idx < Z_ARRVAL_P(stack)->nNumUsed; idx++) { p = Z_ARRVAL_P(stack)->arData + idx; @@ -2079,36 +2142,14 @@ static void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end) } Z_ARRVAL_P(stack)->nNextFreeElement = k; if (should_rehash) { - if (Z_ARRVAL_P(stack)->u.flags & HASH_FLAG_PACKED) { - zend_hash_packed_to_hash(Z_ARRVAL_P(stack)); - } else { - zend_hash_rehash(Z_ARRVAL_P(stack)); - } + zend_hash_rehash(Z_ARRVAL_P(stack)); } - } else if (!key && Z_ARRVAL_P(stack)->nNextFreeElement > 0 && index >= (zend_ulong)(Z_ARRVAL_P(stack)->nNextFreeElement - 1)) { - Z_ARRVAL_P(stack)->nNextFreeElement = Z_ARRVAL_P(stack)->nNextFreeElement - 1; } zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack)); } /* }}} */ -/* {{{ proto mixed array_pop(array stack) - Pops an element off the end of the array */ -PHP_FUNCTION(array_pop) -{ - _phpi_pop(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); -} -/* }}} */ - -/* {{{ proto mixed array_shift(array stack) - Pops an element off the beginning of the array */ -PHP_FUNCTION(array_shift) -{ - _phpi_pop(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); -} -/* }}} */ - /* {{{ proto int array_unshift(array stack, mixed var [, mixed ...]) Pushes elements onto the beginning of the array */ PHP_FUNCTION(array_unshift)