summaryrefslogtreecommitdiff
path: root/Zend/zend_API.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_API.c')
-rw-r--r--Zend/zend_API.c332
1 files changed, 187 insertions, 145 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 55d325c8fa..18d8382934 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 Zend Technologies Ltd. (http://www.zend.com) |
+ | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -15,6 +15,7 @@
| Authors: Andi Gutmans <andi@zend.com> |
| Zeev Suraski <zeev@zend.com> |
| Andrei Zmievski <andrei@php.net> |
+ | Dmitry Stogov <dmitry@zend.com> |
+----------------------------------------------------------------------+
*/
@@ -24,6 +25,7 @@
#include "zend_execute.h"
#include "zend_API.h"
#include "zend_modules.h"
+#include "zend_extensions.h"
#include "zend_constants.h"
#include "zend_exceptions.h"
#include "zend_closures.h"
@@ -149,7 +151,7 @@ ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array) /
}
/* }}} */
-ZEND_API void zend_wrong_param_count(void) /* {{{ */
+ZEND_API ZEND_COLD void zend_wrong_param_count(void) /* {{{ */
{
const char *space;
const char *class_name = get_active_class_name(&space);
@@ -182,6 +184,8 @@ ZEND_API char *zend_get_type_by_const(int type) /* {{{ */
return "callable";
case IS_ARRAY:
return "array";
+ case IS_VOID:
+ return "void";
default:
return "unknown";
}
@@ -196,7 +200,7 @@ ZEND_API char *zend_zval_type_name(const zval *arg) /* {{{ */
/* }}} */
#ifdef FAST_ZPP
-ZEND_API void ZEND_FASTCALL zend_wrong_paramers_count_error(int num_args, int min_num_args, int max_num_args) /* {{{ */
+ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(int num_args, int min_num_args, int max_num_args) /* {{{ */
{
zend_function *active_function = EG(current_execute_data)->func;
const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
@@ -212,7 +216,7 @@ ZEND_API void ZEND_FASTCALL zend_wrong_paramers_count_error(int num_args, int mi
}
/* }}} */
-ZEND_API void ZEND_FASTCALL zend_wrong_paramer_type_error(int num, zend_expected_type expected_type, zval *arg) /* {{{ */
+ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(int num, zend_expected_type expected_type, zval *arg) /* {{{ */
{
const char *space;
const char *class_name = get_active_class_name(&space);
@@ -226,7 +230,7 @@ ZEND_API void ZEND_FASTCALL zend_wrong_paramer_type_error(int num, zend_expected
}
/* }}} */
-ZEND_API void ZEND_FASTCALL zend_wrong_paramer_class_error(int num, char *name, zval *arg) /* {{{ */
+ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(int num, char *name, zval *arg) /* {{{ */
{
const char *space;
const char *class_name = get_active_class_name(&space);
@@ -236,7 +240,7 @@ ZEND_API void ZEND_FASTCALL zend_wrong_paramer_class_error(int num, char *name,
}
/* }}} */
-ZEND_API void ZEND_FASTCALL zend_wrong_callback_error(int severity, int num, char *error) /* {{{ */
+ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int severity, int num, char *error) /* {{{ */
{
const char *space;
const char *class_name = get_active_class_name(&space);
@@ -245,7 +249,7 @@ ZEND_API void ZEND_FASTCALL zend_wrong_callback_error(int severity, int num, cha
zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a valid callback, %s",
class_name, space, get_active_function_name(), num, error);
} else if (severity == E_ERROR) {
- zend_throw_error(zend_ce_error, "%s%s%s() expects parameter %d to be a valid callback, %s",
+ zend_throw_error(zend_ce_type_error, "%s%s%s() expects parameter %d to be a valid callback, %s",
class_name, space, get_active_function_name(), num, error);
} else {
zend_error(severity, "%s%s%s() expects parameter %d to be a valid callback, %s",
@@ -366,11 +370,7 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_weak(zval *arg, zend_long *de
if (UNEXPECTED(zend_isnan(Z_DVAL_P(arg)))) {
return 0;
}
- if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(Z_DVAL_P(arg)))) {
- *dest = (Z_DVAL_P(arg) > 0) ? ZEND_LONG_MAX : ZEND_LONG_MIN;
- } else {
- *dest = zend_dval_to_lval(Z_DVAL_P(arg));
- }
+ *dest = zend_dval_to_lval_cap(Z_DVAL_P(arg));
} else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
double d;
int type;
@@ -380,11 +380,7 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_weak(zval *arg, zend_long *de
if (UNEXPECTED(zend_isnan(d))) {
return 0;
}
- if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(d))) {
- *dest = (d > 0) ? ZEND_LONG_MAX : ZEND_LONG_MIN;
- } else {
- *dest = zend_dval_to_lval(d);
- }
+ *dest = zend_dval_to_lval_cap(d);
} else {
return 0;
}
@@ -499,14 +495,16 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
const char *spec_walk = *spec;
char c = *spec_walk++;
int check_null = 0;
+ int separate = 0;
zval *real_arg = arg;
/* scan through modifiers */
ZVAL_DEREF(arg);
while (1) {
if (*spec_walk == '/') {
- SEPARATE_ZVAL(arg);
+ SEPARATE_ZVAL_NOREF(arg);
real_arg = arg;
+ separate = 1;
} else if (*spec_walk == '!') {
check_null = 1;
} else {
@@ -626,7 +624,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
{
HashTable **p = va_arg(*va, HashTable **);
- if (!zend_parse_arg_array_ht(arg, p, check_null, c == 'H')) {
+ if (!zend_parse_arg_array_ht(arg, p, check_null, c == 'H', separate)) {
return "array";
}
}
@@ -790,7 +788,7 @@ ZEND_API int zend_parse_parameter(int flags, int arg_num, zval *arg, const char
return ret;
}
-static void zend_parse_parameters_debug_error(const char *msg) {
+static ZEND_COLD void zend_parse_parameters_debug_error(const char *msg) {
zend_function *active_function = EG(current_execute_data)->func;
const char *class_name = active_function->common.scope
? ZSTR_VAL(active_function->common.scope->name) : "";
@@ -869,12 +867,11 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
max_num_args = -1;
}
- if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) {
+ if (num_args < min_num_args || (num_args > max_num_args && max_num_args >= 0)) {
if (!(flags & ZEND_PARSE_PARAMS_QUIET)) {
zend_function *active_function = EG(current_execute_data)->func;
const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
- zend_bool throw_exception =
- ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW);
+ zend_bool throw_exception = ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW);
zend_internal_type_error(throw_exception, "%s%s%s() expects %s %d parameter%s, %d given",
class_name,
class_name[0] ? "::" : "",
@@ -937,27 +934,11 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
}
/* }}} */
-#define RETURN_IF_ZERO_ARGS(num_args, type_spec, flags) do { \
- int __num_args = (num_args); \
- if (0 == (type_spec)[0] && 0 != __num_args && !(flags & ZEND_PARSE_PARAMS_QUIET)) { \
- const char *__space; \
- const char * __class_name = get_active_class_name(&__space); \
- zend_bool throw_exception = \
- ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW); \
- zend_internal_type_error(throw_exception, \
- "%s%s%s() expects exactly 0 parameters, %d given", \
- __class_name, __space, get_active_function_name(), __num_args); \
- return FAILURE; \
- } \
-} while(0)
-
ZEND_API int zend_parse_parameters_ex(int flags, int num_args, const char *type_spec, ...) /* {{{ */
{
va_list va;
int retval;
- RETURN_IF_ZERO_ARGS(num_args, type_spec, flags);
-
va_start(va, type_spec);
retval = zend_parse_va_args(num_args, type_spec, &va, flags);
va_end(va);
@@ -972,8 +953,6 @@ ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...) /*
int retval;
int flags = 0;
- RETURN_IF_ZERO_ARGS(num_args, type_spec, flags);
-
va_start(va, type_spec);
retval = zend_parse_va_args(num_args, type_spec, &va, flags);
va_end(va);
@@ -988,8 +967,6 @@ ZEND_API int zend_parse_parameters_throw(int num_args, const char *type_spec, ..
int retval;
int flags = ZEND_PARSE_PARAMS_THROW;
- RETURN_IF_ZERO_ARGS(num_args, type_spec, flags);
-
va_start(va, type_spec);
retval = zend_parse_va_args(num_args, type_spec, &va, flags);
va_end(va);
@@ -1014,14 +991,11 @@ ZEND_API int zend_parse_method_parameters(int num_args, zval *this_ptr, const ch
zend_bool is_method = EG(current_execute_data)->func->common.scope != NULL;
if (!is_method || !this_ptr || Z_TYPE_P(this_ptr) != IS_OBJECT) {
- RETURN_IF_ZERO_ARGS(num_args, p, flags);
-
va_start(va, type_spec);
retval = zend_parse_va_args(num_args, type_spec, &va, flags);
va_end(va);
} else {
p++;
- RETURN_IF_ZERO_ARGS(num_args, p, flags);
va_start(va, type_spec);
@@ -1050,15 +1024,11 @@ ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args, zval *this
zend_class_entry *ce;
if (!this_ptr) {
- RETURN_IF_ZERO_ARGS(num_args, p, flags);
-
va_start(va, type_spec);
retval = zend_parse_va_args(num_args, type_spec, &va, flags);
va_end(va);
} else {
p++;
- RETURN_IF_ZERO_ARGS(num_args, p, flags);
-
va_start(va, type_spec);
object = va_arg(va, zval **);
@@ -1095,11 +1065,11 @@ ZEND_API int _array_init(zval *arg, uint32_t size ZEND_FILE_LINE_DC) /* {{{ */
ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */
{
const zend_object_handlers *obj_ht = Z_OBJ_HT_P(obj);
- zend_class_entry *old_scope = EG(scope);
+ zend_class_entry *old_scope = EG(fake_scope);
zend_string *key;
zval *value;
- EG(scope) = Z_OBJCE_P(obj);
+ EG(fake_scope) = Z_OBJCE_P(obj);
ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, value) {
if (key) {
zval member;
@@ -1108,7 +1078,7 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */
obj_ht->write_property(obj, &member, value, NULL);
}
} ZEND_HASH_FOREACH_END();
- EG(scope) = old_scope;
+ EG(fake_scope) = old_scope;
}
/* }}} */
@@ -1151,17 +1121,15 @@ ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
}
}
} else {
- zend_class_entry **scope = EG(current_execute_data) ? &EG(scope) : &CG(active_class_entry);
- zend_class_entry *old_scope = *scope;
zend_class_entry *ce;
+ zend_class_constant *c;
zval *val;
zend_property_info *prop_info;
- *scope = class_type;
- ZEND_HASH_FOREACH_VAL(&class_type->constants_table, val) {
- ZVAL_DEREF(val);
+ ZEND_HASH_FOREACH_PTR(&class_type->constants_table, c) {
+ val = &c->value;
if (Z_CONSTANT_P(val)) {
- if (UNEXPECTED(zval_update_constant_ex(val, 1, class_type) != SUCCESS)) {
+ if (UNEXPECTED(zval_update_constant_ex(val, class_type) != SUCCESS)) {
return FAILURE;
}
}
@@ -1178,8 +1146,7 @@ ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
}
ZVAL_DEREF(val);
if (Z_CONSTANT_P(val)) {
- *scope = ce;
- if (UNEXPECTED(zval_update_constant_ex(val, 1, NULL) != SUCCESS)) {
+ if (UNEXPECTED(zval_update_constant_ex(val, ce) != SUCCESS)) {
return FAILURE;
}
}
@@ -1187,8 +1154,6 @@ ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
} ZEND_HASH_FOREACH_END();
ce = ce->parent;
}
-
- *scope = old_scope;
}
}
return SUCCESS;
@@ -1220,11 +1185,11 @@ ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properti
{
object->properties = properties;
if (object->ce->default_properties_count) {
- zval *prop;
- zend_string *key;
- zend_property_info *property_info;
+ zval *prop;
+ zend_string *key;
+ zend_property_info *property_info;
- ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) {
+ ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) {
property_info = zend_get_property_info(object->ce, key, 1);
if (property_info != ZEND_WRONG_PROPERTY_INFO &&
property_info &&
@@ -1242,26 +1207,54 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties)
{
zval *prop, tmp;
zend_string *key;
+ zend_long h;
zend_property_info *property_info;
- ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) {
- property_info = zend_get_property_info(object->ce, key, 1);
- if (property_info != ZEND_WRONG_PROPERTY_INFO &&
- property_info &&
- (property_info->flags & ZEND_ACC_STATIC) == 0) {
- zval *slot = OBJ_PROP(object, property_info->offset);
- zval_ptr_dtor(slot);
- ZVAL_COPY_VALUE(slot, prop);
- zval_add_ref(slot);
- if (object->properties) {
- ZVAL_INDIRECT(&tmp, slot);
- zend_hash_update(object->properties, key, &tmp);
+ ZEND_HASH_FOREACH_KEY_VAL(properties, h, key, prop) {
+ if (key) {
+ if (ZSTR_VAL(key)[0] == '\0') {
+ const char *class_name, *prop_name;
+ size_t prop_name_len;
+ if (zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_name_len) == SUCCESS) {
+ zend_string *pname = zend_string_init(prop_name, prop_name_len, 0);
+ zend_class_entry *prev_scope = EG(fake_scope);
+ if (class_name && class_name[0] != '*') {
+ zend_string *cname = zend_string_init(class_name, strlen(class_name), 0);
+ EG(fake_scope) = zend_lookup_class(cname);
+ zend_string_release(cname);
+ }
+ property_info = zend_get_property_info(object->ce, pname, 1);
+ zend_string_release(pname);
+ EG(fake_scope) = prev_scope;
+ } else {
+ property_info = ZEND_WRONG_PROPERTY_INFO;
+ }
+ } else {
+ property_info = zend_get_property_info(object->ce, key, 1);
+ }
+ if (property_info != ZEND_WRONG_PROPERTY_INFO &&
+ property_info &&
+ (property_info->flags & ZEND_ACC_STATIC) == 0) {
+ zval *slot = OBJ_PROP(object, property_info->offset);
+ zval_ptr_dtor(slot);
+ ZVAL_COPY_VALUE(slot, prop);
+ zval_add_ref(slot);
+ if (object->properties) {
+ ZVAL_INDIRECT(&tmp, slot);
+ zend_hash_update(object->properties, key, &tmp);
+ }
+ } else {
+ if (!object->properties) {
+ rebuild_object_properties(object);
+ }
+ prop = zend_hash_update(object->properties, key, prop);
+ zval_add_ref(prop);
}
} else {
if (!object->properties) {
rebuild_object_properties(object);
}
- prop = zend_hash_update(object->properties, key, prop);
+ prop = zend_hash_index_update(object->properties, h, prop);
zval_add_ref(prop);
}
} ZEND_HASH_FOREACH_END();
@@ -1276,11 +1269,11 @@ ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type
{
if (UNEXPECTED(class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) {
if (class_type->ce_flags & ZEND_ACC_INTERFACE) {
- zend_throw_error(zend_ce_error, "Cannot instantiate interface %s", ZSTR_VAL(class_type->name));
+ zend_throw_error(NULL, "Cannot instantiate interface %s", ZSTR_VAL(class_type->name));
} else if (class_type->ce_flags & ZEND_ACC_TRAIT) {
- zend_throw_error(zend_ce_error, "Cannot instantiate trait %s", ZSTR_VAL(class_type->name));
+ zend_throw_error(NULL, "Cannot instantiate trait %s", ZSTR_VAL(class_type->name));
} else {
- zend_throw_error(zend_ce_error, "Cannot instantiate abstract class %s", ZSTR_VAL(class_type->name));
+ zend_throw_error(NULL, "Cannot instantiate abstract class %s", ZSTR_VAL(class_type->name));
}
ZVAL_NULL(arg);
Z_OBJ_P(arg) = NULL;
@@ -1321,13 +1314,6 @@ ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC) /* {{{ */
}
/* }}} */
-ZEND_API int add_assoc_function(zval *arg, const char *key, void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS)) /* {{{ */
-{
- zend_error(E_WARNING, "add_assoc_function() is no longer supported");
- return FAILURE;
-}
-/* }}} */
-
ZEND_API int add_assoc_long_ex(zval *arg, const char *key, size_t key_len, zend_long n) /* {{{ */
{
zval *ret, tmp;
@@ -1650,7 +1636,7 @@ ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */
result = zend_symtable_update(ht, ZSTR_EMPTY_ALLOC(), value);
break;
case IS_RESOURCE:
- zend_error(E_NOTICE, "Resource ID#" ZEND_LONG_FMT " used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key));
+ zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key));
result = zend_hash_index_update(ht, Z_RES_HANDLE_P(key), value);
break;
case IS_FALSE:
@@ -2014,7 +2000,7 @@ ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module) /
lcname = zend_string_alloc(name_len, 0);
zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);
- if (zend_hash_exists(&module_registry, lcname)) {
+ if (zend_hash_exists(&module_registry, lcname) || zend_get_extension(dep->name)) {
zend_string_free(lcname);
/* TODO: Check version relationship */
zend_error(E_CORE_WARNING, "Cannot load module '%s' because conflicting module '%s' is already loaded", module->name, dep->name);
@@ -2148,6 +2134,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
}
internal_function->type = ZEND_INTERNAL_FUNCTION;
internal_function->module = EG(current_module);
+ memset(internal_function->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
if (scope) {
class_name_len = ZSTR_LEN(scope->name);
@@ -2828,7 +2815,7 @@ ZEND_API int zend_disable_class(char *class_name, size_t class_name_length) /* {
}
/* }}} */
-static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache *fcc, int *strict_class, char **error) /* {{{ */
+static int zend_is_callable_check_class(zend_string *name, zend_class_entry *scope, zend_fcall_info_cache *fcc, int *strict_class, char **error) /* {{{ */
{
int ret = 0;
zend_class_entry *ce;
@@ -2841,24 +2828,24 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache
*strict_class = 0;
if (zend_string_equals_literal(lcname, "self")) {
- if (!EG(scope)) {
+ if (!scope) {
if (error) *error = estrdup("cannot access self:: when no class scope is active");
} else {
fcc->called_scope = zend_get_called_scope(EG(current_execute_data));
- fcc->calling_scope = EG(scope);
+ fcc->calling_scope = scope;
if (!fcc->object) {
fcc->object = zend_get_this_object(EG(current_execute_data));
}
ret = 1;
}
} else if (zend_string_equals_literal(lcname, "parent")) {
- if (!EG(scope)) {
+ if (!scope) {
if (error) *error = estrdup("cannot access parent:: when no class scope is active");
- } else if (!EG(scope)->parent) {
+ } else if (!scope->parent) {
if (error) *error = estrdup("cannot access parent:: when current class scope has no parent");
} else {
fcc->called_scope = zend_get_called_scope(EG(current_execute_data));
- fcc->calling_scope = EG(scope)->parent;
+ fcc->calling_scope = scope->parent;
if (!fcc->object) {
fcc->object = zend_get_this_object(EG(current_execute_data));
}
@@ -2920,9 +2907,9 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
zend_string *lmname;
const char *colon;
size_t clen, mlen;
- zend_class_entry *last_scope;
HashTable *ftable;
int call_via_handler = 0;
+ zend_class_entry *scope;
ALLOCA_FLAG(use_heap)
if (error) {
@@ -2947,6 +2934,7 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
if (lmname != Z_STR_P(callable)) {
ZSTR_ALLOCA_FREE(lmname, use_heap);
}
+ fcc->initialized = 1;
return 1;
} else {
if (lmname == Z_STR_P(callable)) {
@@ -2957,6 +2945,7 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
zend_str_tolower(ZSTR_VAL(lmname), ZSTR_LEN(lmname));
if ((fcc->function_handler = zend_hash_find_ptr(EG(function_table), lmname)) != NULL) {
ZSTR_ALLOCA_FREE(lmname, use_heap);
+ fcc->initialized = 1;
return 1;
}
}
@@ -2981,19 +2970,18 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
/* This is a compound name.
* Try to fetch class and then find static method. */
- last_scope = EG(scope);
if (ce_org) {
- EG(scope) = ce_org;
+ scope = ce_org;
+ } else {
+ scope = zend_get_executed_scope();
}
cname = zend_string_init(Z_STRVAL_P(callable), clen, 0);
- if (!zend_is_callable_check_class(cname, fcc, &strict_class, error)) {
+ if (!zend_is_callable_check_class(cname, scope, fcc, &strict_class, error)) {
zend_string_release(cname);
- EG(scope) = last_scope;
return 0;
}
zend_string_release(cname);
- EG(scope) = last_scope;
ftable = &fcc->calling_scope->function_table;
if (ce_org && !instanceof_function(ce_org, fcc->calling_scope)) {
@@ -3027,14 +3015,17 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
} else if ((fcc->function_handler = zend_hash_find_ptr(ftable, lmname)) != NULL) {
retval = 1;
if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) &&
- !strict_class && EG(scope) &&
- instanceof_function(fcc->function_handler->common.scope, EG(scope))) {
- zend_function *priv_fbc;
-
- if ((priv_fbc = zend_hash_find_ptr(&EG(scope)->function_table, lmname)) != NULL
- && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE
- && priv_fbc->common.scope == EG(scope)) {
- fcc->function_handler = priv_fbc;
+ !strict_class) {
+ scope = zend_get_executed_scope();
+ if (scope &&
+ instanceof_function(fcc->function_handler->common.scope, scope)) {
+ zend_function *priv_fbc;
+
+ if ((priv_fbc = zend_hash_find_ptr(&scope->function_table, lmname)) != NULL
+ && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE
+ && priv_fbc->common.scope == scope) {
+ fcc->function_handler = priv_fbc;
+ }
}
}
if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0 &&
@@ -3042,13 +3033,15 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
((fcc->object && fcc->calling_scope->__call) ||
(!fcc->object && fcc->calling_scope->__callstatic)))) {
if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
- if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : EG(scope), lmname)) {
+ scope = zend_get_executed_scope();
+ if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : scope, lmname)) {
retval = 0;
fcc->function_handler = NULL;
goto get_function_via_handler;
}
} else if (fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED) {
- if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
+ scope = zend_get_executed_scope();
+ if (!zend_check_protected(fcc->function_handler->common.scope, scope)) {
retval = 0;
fcc->function_handler = NULL;
goto get_function_via_handler;
@@ -3107,7 +3100,7 @@ get_function_via_handler:
zend_spprintf(error, 0, "cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
retval = 0;
} else {
- zend_throw_error(zend_ce_error, "Cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
+ zend_throw_error(NULL, "Cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
return 0;
}
} else if (!fcc->object && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
@@ -3131,7 +3124,7 @@ get_function_via_handler:
}
} else if (retval) {
if (severity == E_ERROR) {
- zend_throw_error(zend_ce_error, "Non-static method %s::%s() %s be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name), verb);
+ zend_throw_error(NULL, "Non-static method %s::%s() %s be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name), verb);
} else {
zend_error(severity, "Non-static method %s::%s() %s be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name), verb);
}
@@ -3139,7 +3132,8 @@ get_function_via_handler:
}
if (retval && (check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) {
if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
- if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : EG(scope), lmname)) {
+ scope = zend_get_executed_scope();
+ if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : scope, lmname)) {
if (error) {
if (*error) {
efree(*error);
@@ -3149,7 +3143,8 @@ get_function_via_handler:
retval = 0;
}
} else if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED)) {
- if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
+ scope = zend_get_executed_scope();
+ if (!zend_check_protected(fcc->function_handler->common.scope, scope)) {
if (error) {
if (*error) {
efree(*error);
@@ -3286,7 +3281,7 @@ again:
return 1;
}
- if (!zend_is_callable_check_class(Z_STR_P(obj), fcc, &strict_class, error)) {
+ if (!zend_is_callable_check_class(Z_STR_P(obj), zend_get_executed_scope(), fcc, &strict_class, error)) {
return 0;
}
@@ -3360,6 +3355,7 @@ again:
memcpy(ZSTR_VAL(*callable_name), ZSTR_VAL(ce->name), ZSTR_LEN(ce->name));
memcpy(ZSTR_VAL(*callable_name) + ZSTR_LEN(ce->name), "::__invoke", sizeof("::__invoke"));
}
+ fcc->initialized = 1;
return 1;
}
if (callable_name) {
@@ -3419,14 +3415,12 @@ ZEND_API int zend_fcall_info_init(zval *callable, uint check_flags, zend_fcall_i
}
fci->size = sizeof(*fci);
- fci->function_table = fcc->calling_scope ? &fcc->calling_scope->function_table : EG(function_table);
fci->object = fcc->object;
ZVAL_COPY_VALUE(&fci->function_name, callable);
fci->retval = NULL;
fci->param_count = 0;
fci->params = NULL;
fci->no_separation = 1;
- fci->symbol_table = NULL;
return SUCCESS;
}
@@ -3745,13 +3739,51 @@ ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *nam
}
/* }}} */
-ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value) /* {{{ */
+ZEND_API int zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *name, zval *value, int access_type, zend_string *doc_comment) /* {{{ */
{
+ zend_class_constant *c;
+
+ if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+ if (access_type != ZEND_ACC_PUBLIC) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface constant %s::%s must be public", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+ }
+ }
+
+ if (zend_string_equals_literal_ci(name, "class")) {
+ zend_error_noreturn(ce->type == ZEND_INTERNAL_CLASS ? E_CORE_ERROR : E_COMPILE_ERROR,
+ "A class constant must not be called 'class'; it is reserved for class name fetching");
+ }
+
+ if (ce->type == ZEND_INTERNAL_CLASS) {
+ c = pemalloc(sizeof(zend_class_constant), 1);
+ } else {
+ c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
+ }
+ ZVAL_COPY_VALUE(&c->value, value);
+ Z_ACCESS_FLAGS(c->value) = access_type;
+ c->doc_comment = doc_comment;
+ c->ce = ce;
if (Z_CONSTANT_P(value)) {
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
}
- return zend_hash_str_update(&ce->constants_table, name, name_length, value) ?
- SUCCESS : FAILURE;
+
+ if (!zend_hash_add_ptr(&ce->constants_table, name, c)) {
+ zend_error_noreturn(ce->type == ZEND_INTERNAL_CLASS ? E_CORE_ERROR : E_COMPILE_ERROR,
+ "Cannot redefine class constant %s::%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+ }
+
+ return SUCCESS;
+}
+/* }}} */
+
+ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value) /* {{{ */
+{
+ int ret;
+
+ zend_string *key = zend_string_init(name, name_length, ce->type & ZEND_INTERNAL_CLASS);
+ ret = zend_declare_class_constant_ex(ce, key, value, ZEND_ACC_PUBLIC, NULL);
+ zend_string_release(key);
+ return ret;
}
/* }}} */
@@ -3809,9 +3841,9 @@ ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char
ZEND_API void zend_update_property_ex(zend_class_entry *scope, zval *object, zend_string *name, zval *value) /* {{{ */
{
zval property;
- zend_class_entry *old_scope = EG(scope);
+ zend_class_entry *old_scope = EG(fake_scope);
- EG(scope) = scope;
+ EG(fake_scope) = scope;
if (!Z_OBJ_HT_P(object)->write_property) {
zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, ZSTR_VAL(Z_OBJCE_P(object)->name));
@@ -3819,16 +3851,16 @@ ZEND_API void zend_update_property_ex(zend_class_entry *scope, zval *object, zen
ZVAL_STR(&property, name);
Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL);
- EG(scope) = old_scope;
+ EG(fake_scope) = old_scope;
}
/* }}} */
ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zval *value) /* {{{ */
{
zval property;
- zend_class_entry *old_scope = EG(scope);
+ zend_class_entry *old_scope = EG(fake_scope);
- EG(scope) = scope;
+ EG(fake_scope) = scope;
if (!Z_OBJ_HT_P(object)->write_property) {
zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, ZSTR_VAL(Z_OBJCE_P(object)->name));
@@ -3837,7 +3869,7 @@ ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const
Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL);
zval_ptr_dtor(&property);
- EG(scope) = old_scope;
+ EG(fake_scope) = old_scope;
}
/* }}} */
@@ -3909,12 +3941,12 @@ ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object
ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, size_t name_length, zval *value) /* {{{ */
{
zval *property;
- zend_class_entry *old_scope = EG(scope);
+ zend_class_entry *old_scope = EG(fake_scope);
zend_string *key = zend_string_init(name, name_length, 0);
- EG(scope) = scope;
+ EG(fake_scope) = scope;
property = zend_std_get_static_property(scope, key, 0);
- EG(scope) = old_scope;
+ EG(fake_scope) = old_scope;
zend_string_free(key);
if (!property) {
return FAILURE;
@@ -3923,7 +3955,7 @@ ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *na
if (Z_ISREF_P(property)) {
zval_dtor(property);
ZVAL_COPY_VALUE(property, value);
- if (Z_REFCOUNT_P(value) > 0) {
+ if (Z_REFCOUNTED_P(value) && Z_REFCOUNT_P(value) > 0) {
zval_opt_copy_ctor(property);
}
} else {
@@ -4001,22 +4033,33 @@ ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const
}
/* }}} */
-ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_bool silent, zval *rv) /* {{{ */
+ZEND_API zval *zend_read_property_ex(zend_class_entry *scope, zval *object, zend_string *name, zend_bool silent, zval *rv) /* {{{ */
{
zval property, *value;
- zend_class_entry *old_scope = EG(scope);
+ zend_class_entry *old_scope = EG(fake_scope);
- EG(scope) = scope;
+ EG(fake_scope) = scope;
if (!Z_OBJ_HT_P(object)->read_property) {
zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be read", name, ZSTR_VAL(Z_OBJCE_P(object)->name));
}
- ZVAL_STRINGL(&property, name, name_length);
+ ZVAL_STR(&property, name);
value = Z_OBJ_HT_P(object)->read_property(object, &property, silent?BP_VAR_IS:BP_VAR_R, NULL, rv);
- zval_ptr_dtor(&property);
- EG(scope) = old_scope;
+ EG(fake_scope) = old_scope;
+ return value;
+}
+/* }}} */
+
+ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_bool silent, zval *rv) /* {{{ */
+{
+ zval *value;
+ zend_string *str;
+
+ str = zend_string_init(name, name_length, 0);
+ value = zend_read_property_ex(scope, object, str, silent, rv);
+ zend_string_release(str);
return value;
}
/* }}} */
@@ -4024,12 +4067,12 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const c
ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, size_t name_length, zend_bool silent) /* {{{ */
{
zval *property;
- zend_class_entry *old_scope = EG(scope);
+ zend_class_entry *old_scope = EG(fake_scope);
zend_string *key = zend_string_init(name, name_length, 0);
- EG(scope) = scope;
+ EG(fake_scope) = scope;
property = zend_std_get_static_property(scope, key, silent);
- EG(scope) = old_scope;
+ EG(fake_scope) = old_scope;
zend_string_free(key);
return property;
@@ -4106,8 +4149,7 @@ ZEND_API zend_string* zend_find_alias_name(zend_class_entry *ce, zend_string *na
if ((alias_ptr = ce->trait_aliases)) {
alias = *alias_ptr;
while (alias) {
- if (ZSTR_LEN(alias->alias) == ZSTR_LEN(name) &&
- !strncasecmp(ZSTR_VAL(name), ZSTR_VAL(alias->alias), ZSTR_LEN(alias->alias))) {
+ if (alias->alias && zend_string_equals_ci(alias->alias, name)) {
return alias->alias;
}
alias_ptr++;