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.c508
1 files changed, 276 insertions, 232 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index e0bb034adc..a6aa4e5837 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -30,9 +30,7 @@
#include "zend_closures.h"
#include "zend_inheritance.h"
-#ifdef HAVE_STDARG_H
#include <stdarg.h>
-#endif
/* these variables are true statics/globals, and have to be mutex'ed on every access */
ZEND_API HashTable module_registry;
@@ -1174,9 +1172,22 @@ ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
} else {
val = (zval*)((char*)class_type->default_properties_table + prop_info->offset - OBJ_PROP_TO_OFFSET(0));
}
- ZVAL_DEREF(val);
if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
- if (UNEXPECTED(zval_update_constant_ex(val, ce) != SUCCESS)) {
+ if (prop_info->type) {
+ zval tmp;
+
+ ZVAL_COPY(&tmp, val);
+ if (UNEXPECTED(zval_update_constant_ex(&tmp, ce) != SUCCESS)) {
+ return FAILURE;
+ }
+ /* property initializers must always be evaluated with strict types */;
+ if (UNEXPECTED(!zend_verify_property_type(prop_info, &tmp, /* strict */ 1))) {
+ zval_ptr_dtor(&tmp);
+ return FAILURE;
+ }
+ zval_ptr_dtor(val);
+ ZVAL_COPY_VALUE(val, &tmp);
+ } else if (UNEXPECTED(zval_update_constant_ex(val, ce) != SUCCESS)) {
return FAILURE;
}
}
@@ -1192,7 +1203,7 @@ ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
}
/* }}} */
-ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
+static zend_always_inline void _object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
{
if (class_type->default_properties_count) {
zval *src = class_type->default_properties_table;
@@ -1212,11 +1223,17 @@ ZEND_API void object_properties_init(zend_object *object, zend_class_entry *clas
dst++;
} while (src != end);
}
- object->properties = NULL;
}
}
/* }}} */
+ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
+{
+ object->properties = NULL;
+ _object_properties_init(object, class_type);
+}
+/* }}} */
+
ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properties) /* {{{ */
{
object->properties = properties;
@@ -1231,7 +1248,18 @@ ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properti
property_info &&
(property_info->flags & ZEND_ACC_STATIC) == 0) {
zval *slot = OBJ_PROP(object, property_info->offset);
- ZVAL_COPY_VALUE(slot, prop);
+
+ if (UNEXPECTED(property_info->type)) {
+ zval tmp;
+
+ ZVAL_COPY_VALUE(&tmp, prop);
+ if (UNEXPECTED(!zend_verify_property_type(property_info, &tmp, 0))) {
+ continue;
+ }
+ ZVAL_COPY_VALUE(slot, &tmp);
+ } else {
+ ZVAL_COPY_VALUE(slot, prop);
+ }
ZVAL_INDIRECT(prop, slot);
}
} ZEND_HASH_FOREACH_END();
@@ -1301,7 +1329,7 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties)
* class and all props being public. If only a subset is given or the class
* has protected members then you need to merge the properties separately by
* calling zend_merge_properties(). */
-ZEND_API int object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties) /* {{{ */
+static zend_always_inline int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties) /* {{{ */
{
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) {
@@ -1325,11 +1353,13 @@ ZEND_API int object_and_properties_init(zval *arg, zend_class_entry *class_type,
}
if (class_type->create_object == NULL) {
- ZVAL_OBJ(arg, zend_objects_new(class_type));
+ zend_object *obj = zend_objects_new(class_type);
+
+ ZVAL_OBJ(arg, obj);
if (properties) {
- object_properties_init_ex(Z_OBJ_P(arg), properties);
+ object_properties_init_ex(obj, properties);
} else {
- object_properties_init(Z_OBJ_P(arg), class_type);
+ _object_properties_init(obj, class_type);
}
} else {
ZVAL_OBJ(arg, class_type->create_object(class_type));
@@ -1338,9 +1368,15 @@ ZEND_API int object_and_properties_init(zval *arg, zend_class_entry *class_type,
}
/* }}} */
+ZEND_API int object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties) /* {{{ */
+{
+ return _object_and_properties_init(arg, class_type, properties);
+}
+/* }}} */
+
ZEND_API int object_init_ex(zval *arg, zend_class_entry *class_type) /* {{{ */
{
- return object_and_properties_init(arg, class_type, 0);
+ return _object_and_properties_init(arg, class_type, NULL);
}
/* }}} */
@@ -1518,13 +1554,6 @@ ZEND_API int add_index_stringl(zval *arg, zend_ulong index, const char *str, siz
}
/* }}} */
-ZEND_API int add_index_zval(zval *arg, zend_ulong index, zval *value) /* {{{ */
-{
- zend_hash_index_update(Z_ARRVAL_P(arg), index, value);
- return SUCCESS;
-}
-/* }}} */
-
ZEND_API int add_next_index_long(zval *arg, zend_long n) /* {{{ */
{
zval tmp;
@@ -1597,77 +1626,6 @@ ZEND_API int add_next_index_stringl(zval *arg, const char *str, size_t length) /
}
/* }}} */
-ZEND_API int add_next_index_zval(zval *arg, zval *value) /* {{{ */
-{
- return zend_hash_next_index_insert(Z_ARRVAL_P(arg), value) ? SUCCESS : FAILURE;
-}
-/* }}} */
-
-ZEND_API zval *add_get_assoc_string_ex(zval *arg, const char *key, uint32_t key_len, const char *str) /* {{{ */
-{
- zval tmp, *ret;
-
- ZVAL_STRING(&tmp, str);
- ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
- return ret;
-}
-/* }}} */
-
-ZEND_API zval *add_get_assoc_stringl_ex(zval *arg, const char *key, uint32_t key_len, const char *str, size_t length) /* {{{ */
-{
- zval tmp, *ret;
-
- ZVAL_STRINGL(&tmp, str, length);
- ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
- return ret;
-}
-/* }}} */
-
-ZEND_API zval *add_get_index_long(zval *arg, zend_ulong index, zend_long l) /* {{{ */
-{
- zval tmp;
-
- ZVAL_LONG(&tmp, l);
- return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
-}
-/* }}} */
-
-ZEND_API zval *add_get_index_double(zval *arg, zend_ulong index, double d) /* {{{ */
-{
- zval tmp;
-
- ZVAL_DOUBLE(&tmp, d);
- return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
-}
-/* }}} */
-
-ZEND_API zval *add_get_index_str(zval *arg, zend_ulong index, zend_string *str) /* {{{ */
-{
- zval tmp;
-
- ZVAL_STR(&tmp, str);
- return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
-}
-/* }}} */
-
-ZEND_API zval *add_get_index_string(zval *arg, zend_ulong index, const char *str) /* {{{ */
-{
- zval tmp;
-
- ZVAL_STRING(&tmp, str);
- return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
-}
-/* }}} */
-
-ZEND_API zval *add_get_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length) /* {{{ */
-{
- zval tmp;
-
- ZVAL_STRINGL(&tmp, str, length);
- return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
-}
-/* }}} */
-
ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */
{
zval *result;
@@ -1712,52 +1670,37 @@ ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */
ZEND_API int add_property_long_ex(zval *arg, const char *key, size_t key_len, zend_long n) /* {{{ */
{
zval tmp;
- zval z_key;
ZVAL_LONG(&tmp, n);
- ZVAL_STRINGL(&z_key, key, key_len);
- Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
- zval_ptr_dtor(&z_key);
- return SUCCESS;
+ return add_property_zval_ex(arg, key, key_len, &tmp);
}
/* }}} */
ZEND_API int add_property_bool_ex(zval *arg, const char *key, size_t key_len, zend_long b) /* {{{ */
{
zval tmp;
- zval z_key;
ZVAL_BOOL(&tmp, b);
- ZVAL_STRINGL(&z_key, key, key_len);
- Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
- zval_ptr_dtor(&z_key);
- return SUCCESS;
+ return add_property_zval_ex(arg, key, key_len, &tmp);
}
/* }}} */
ZEND_API int add_property_null_ex(zval *arg, const char *key, size_t key_len) /* {{{ */
{
zval tmp;
- zval z_key;
ZVAL_NULL(&tmp);
- ZVAL_STRINGL(&z_key, key, key_len);
- Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
- zval_ptr_dtor(&z_key);
- return SUCCESS;
+ return add_property_zval_ex(arg, key, key_len, &tmp);
}
/* }}} */
ZEND_API int add_property_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r) /* {{{ */
{
zval tmp;
- zval z_key;
ZVAL_RES(&tmp, r);
- ZVAL_STRINGL(&z_key, key, key_len);
- Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
+ add_property_zval_ex(arg, key, key_len, &tmp);
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
- zval_ptr_dtor(&z_key);
return SUCCESS;
}
/* }}} */
@@ -1765,26 +1708,19 @@ ZEND_API int add_property_resource_ex(zval *arg, const char *key, size_t key_len
ZEND_API int add_property_double_ex(zval *arg, const char *key, size_t key_len, double d) /* {{{ */
{
zval tmp;
- zval z_key;
ZVAL_DOUBLE(&tmp, d);
- ZVAL_STRINGL(&z_key, key, key_len);
- Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
- zval_ptr_dtor(&z_key);
- return SUCCESS;
+ return add_property_zval_ex(arg, key, key_len, &tmp);
}
/* }}} */
ZEND_API int add_property_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str) /* {{{ */
{
zval tmp;
- zval z_key;
ZVAL_STR(&tmp, str);
- ZVAL_STRINGL(&z_key, key, key_len);
- Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
+ add_property_zval_ex(arg, key, key_len, &tmp);
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
- zval_ptr_dtor(&z_key);
return SUCCESS;
}
/* }}} */
@@ -1792,13 +1728,10 @@ ZEND_API int add_property_str_ex(zval *arg, const char *key, size_t key_len, zen
ZEND_API int add_property_string_ex(zval *arg, const char *key, size_t key_len, const char *str) /* {{{ */
{
zval tmp;
- zval z_key;
ZVAL_STRING(&tmp, str);
- ZVAL_STRINGL(&z_key, key, key_len);
- Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
+ add_property_zval_ex(arg, key, key_len, &tmp);
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
- zval_ptr_dtor(&z_key);
return SUCCESS;
}
/* }}} */
@@ -1806,13 +1739,10 @@ ZEND_API int add_property_string_ex(zval *arg, const char *key, size_t key_len,
ZEND_API int add_property_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length) /* {{{ */
{
zval tmp;
- zval z_key;
ZVAL_STRINGL(&tmp, str, length);
- ZVAL_STRINGL(&z_key, key, key_len);
- Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL);
+ add_property_zval_ex(arg, key, key_len, &tmp);
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
- zval_ptr_dtor(&z_key);
return SUCCESS;
}
/* }}} */
@@ -2410,14 +2340,12 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
scope->__isset = __isset;
scope->__debugInfo = __debugInfo;
if (ctor) {
- ctor->common.fn_flags |= ZEND_ACC_CTOR;
if (ctor->common.fn_flags & ZEND_ACC_STATIC) {
zend_error(error_type, "Constructor %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(ctor->common.function_name));
}
ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
}
if (dtor) {
- dtor->common.fn_flags |= ZEND_ACC_DTOR;
if (dtor->common.fn_flags & ZEND_ACC_STATIC) {
zend_error(error_type, "Destructor %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(dtor->common.function_name));
}
@@ -2477,11 +2405,11 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
}
}
- if (ctor && ctor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE && ctor->common.fn_flags & ZEND_ACC_CTOR) {
+ if (ctor && (ctor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
zend_error_noreturn(E_CORE_ERROR, "Constructor %s::%s() cannot declare a return type", ZSTR_VAL(scope->name), ZSTR_VAL(ctor->common.function_name));
}
- if (dtor && dtor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE && dtor->common.fn_flags & ZEND_ACC_DTOR) {
+ if (dtor && (dtor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
zend_error_noreturn(E_CORE_ERROR, "Destructor %s::%s() cannot declare a return type", ZSTR_VAL(scope->name), ZSTR_VAL(dtor->common.function_name));
}
@@ -2617,28 +2545,22 @@ ZEND_API void zend_activate_modules(void) /* {{{ */
}
/* }}} */
-/* call request shutdown for all modules */
-static int module_registry_cleanup(zval *zv) /* {{{ */
-{
- zend_module_entry *module = Z_PTR_P(zv);
-
- if (module->request_shutdown_func) {
-#if 0
- zend_printf("%s: Request shutdown\n", module->name);
-#endif
- module->request_shutdown_func(module->type, module->module_number);
- }
- return 0;
-}
-/* }}} */
-
ZEND_API void zend_deactivate_modules(void) /* {{{ */
{
EG(current_execute_data) = NULL; /* we're no longer executing anything */
zend_try {
if (EG(full_tables_cleanup)) {
- zend_hash_reverse_apply(&module_registry, module_registry_cleanup);
+ zend_module_entry *module;
+
+ ZEND_HASH_REVERSE_FOREACH_PTR(&module_registry, module) {
+ if (module->request_shutdown_func) {
+#if 0
+ zend_printf("%s: Request shutdown\n", module->name);
+#endif
+ module->request_shutdown_func(module->type, module->module_number);
+ }
+ } ZEND_HASH_FOREACH_END();
} else {
zend_module_entry **p = module_request_shutdown_handlers;
@@ -2664,34 +2586,21 @@ ZEND_API void zend_cleanup_internal_classes(void) /* {{{ */
}
/* }}} */
-int module_registry_unload_temp(const zend_module_entry *module) /* {{{ */
-{
- return (module->type == MODULE_TEMPORARY) ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_STOP;
-}
-/* }}} */
-
-static int module_registry_unload_temp_wrapper(zval *el) /* {{{ */
-{
- zend_module_entry *module = (zend_module_entry *)Z_PTR_P(el);
- return module_registry_unload_temp((const zend_module_entry *)module);
-}
-/* }}} */
-
-static int exec_done_cb(zval *el) /* {{{ */
-{
- zend_module_entry *module = (zend_module_entry *)Z_PTR_P(el);
- if (module->post_deactivate_func) {
- module->post_deactivate_func();
- }
- return 0;
-}
-/* }}} */
-
ZEND_API void zend_post_deactivate_modules(void) /* {{{ */
{
if (EG(full_tables_cleanup)) {
- zend_hash_apply(&module_registry, exec_done_cb);
- zend_hash_reverse_apply(&module_registry, module_registry_unload_temp_wrapper);
+ zend_module_entry *module;
+
+ ZEND_HASH_FOREACH_PTR(&module_registry, module) {
+ if (module->post_deactivate_func) {
+ module->post_deactivate_func();
+ }
+ } ZEND_HASH_FOREACH_END();
+ ZEND_HASH_REVERSE_FOREACH_PTR(&module_registry, module) {
+ if (module->type != MODULE_TEMPORARY) {
+ break;
+ }
+ } ZEND_HASH_FOREACH_END_DEL();
} else {
zend_module_entry **p = module_post_deactivate_handlers;
@@ -2720,7 +2629,7 @@ static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class
class_entry->type = ZEND_INTERNAL_CLASS;
zend_initialize_class_data(class_entry, 0);
- class_entry->ce_flags = ce_flags | ZEND_ACC_CONSTANTS_UPDATED;
+ class_entry->ce_flags = ce_flags | ZEND_ACC_CONSTANTS_UPDATED | ZEND_ACC_LINKED;
class_entry->info.internal.module = EG(current_module);
if (class_entry->info.internal.builtin_functions) {
@@ -2748,6 +2657,7 @@ ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *cla
if (parent_ce) {
zend_do_inheritance(register_class, parent_ce);
+ zend_build_properties_info_table(register_class);
}
return register_class;
}
@@ -2800,7 +2710,9 @@ ZEND_API int zend_register_class_alias_ex(const char *name, size_t name_len, zen
ce = zend_hash_add_ptr(CG(class_table), lcname, ce);
zend_string_release_ex(lcname, 0);
if (ce) {
- ce->refcount++;
+ if (!(ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
+ ce->refcount++;
+ }
return SUCCESS;
}
return FAILURE;
@@ -3110,24 +3022,17 @@ static zend_always_inline int zend_is_callable_check_func(int check_flags, zval
}
}
}
- if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0 &&
+ if (!(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC) &&
+ !(check_flags & IS_CALLABLE_CHECK_NO_ACCESS) &&
(fcc->calling_scope &&
((fcc->object && fcc->calling_scope->__call) ||
(!fcc->object && fcc->calling_scope->__callstatic)))) {
- if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
- 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) {
- 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;
- }
+ scope = zend_get_executed_scope();
+ if (fcc->function_handler->common.scope != scope
+ || !zend_check_protected(zend_get_function_root_class(fcc->function_handler), scope)) {
+ retval = 0;
+ fcc->function_handler = NULL;
+ goto get_function_via_handler;
}
}
} else {
@@ -3137,7 +3042,7 @@ get_function_via_handler:
fcc->function_handler = zend_get_call_trampoline_func(ce_org, mname, 0);
call_via_handler = 1;
retval = 1;
- } else if (fcc->object->handlers->get_method) {
+ } else {
fcc->function_handler = fcc->object->handlers->get_method(&fcc->object, mname, NULL);
if (fcc->function_handler) {
if (strict_class &&
@@ -3213,26 +3118,18 @@ 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) {
- 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);
- }
- zend_spprintf(error, 0, "cannot access private method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
- }
- retval = 0;
- }
- } else if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED)) {
- scope = zend_get_executed_scope();
- if (!zend_check_protected(fcc->function_handler->common.scope, scope)) {
+ if (retval
+ && !(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC)
+ && !(check_flags & IS_CALLABLE_CHECK_NO_ACCESS)) {
+ scope = zend_get_executed_scope();
+ if (fcc->function_handler->common.scope != scope) {
+ if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PRIVATE)
+ || (!zend_check_protected(zend_get_function_root_class(fcc->function_handler), scope))) {
if (error) {
if (*error) {
efree(*error);
}
- zend_spprintf(error, 0, "cannot access protected method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
+ zend_spprintf(error, 0, "cannot access %s method %s::%s()", zend_visibility_string(fcc->function_handler->common.fn_flags), ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
}
retval = 0;
}
@@ -3521,7 +3418,7 @@ ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem) /*
zval *end = p + fci->param_count;
while (p != end) {
- i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
+ i_zval_ptr_dtor(p);
p++;
}
if (free_mem) {
@@ -3696,10 +3593,14 @@ static inline zend_string *zval_make_interned_string(zval *zv) /* {{{ */
return Z_STR_P(zv);
}
-ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment) /* {{{ */
+ZEND_API int zend_declare_typed_property(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment, zend_type type) /* {{{ */
{
zend_property_info *property_info, *property_info_ptr;
+ if (ZEND_TYPE_IS_SET(type)) {
+ ce->ce_flags |= ZEND_ACC_HAS_TYPE_HINTS;
+ }
+
if (ce->type == ZEND_INTERNAL_CLASS) {
property_info = pemalloc(sizeof(zend_property_info), 1);
} else {
@@ -3727,8 +3628,14 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z
ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
}
ZVAL_COPY_VALUE(&ce->default_static_members_table[property_info->offset], property);
- if (ce->type == ZEND_USER_CLASS) {
- ce->static_members_table = ce->default_static_members_table;
+ if (!ZEND_MAP_PTR(ce->static_members_table)) {
+ ZEND_ASSERT(ce->type == ZEND_INTERNAL_CLASS);
+ if (!EG(current_execute_data)) {
+ ZEND_MAP_PTR_NEW(ce->static_members_table);
+ } else {
+ /* internal class loaded by dl() */
+ ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table);
+ }
}
} else {
if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL &&
@@ -3736,10 +3643,20 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z
property_info->offset = property_info_ptr->offset;
zval_ptr_dtor(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)]);
zend_hash_del(&ce->properties_info, name);
+
+ ZEND_ASSERT(ce->type == ZEND_INTERNAL_CLASS);
+ ZEND_ASSERT(ce->properties_info_table != NULL);
+ ce->properties_info_table[OBJ_PROP_TO_NUM(property_info->offset)] = property_info;
} else {
property_info->offset = OBJ_PROP_TO_OFFSET(ce->default_properties_count);
ce->default_properties_count++;
ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
+
+ /* For user classes this is handled during linking */
+ if (ce->type == ZEND_INTERNAL_CLASS) {
+ ce->properties_info_table = perealloc(ce->properties_info_table, sizeof(zend_property_info *) * ce->default_properties_count, 1);
+ ce->properties_info_table[ce->default_properties_count - 1] = property_info;
+ }
}
ZVAL_COPY_VALUE(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)], property);
}
@@ -3771,12 +3688,147 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z
property_info->flags = access_type;
property_info->doc_comment = doc_comment;
property_info->ce = ce;
+ property_info->type = type;
+
zend_hash_update_ptr(&ce->properties_info, name, property_info);
return SUCCESS;
}
/* }}} */
+ZEND_API int zend_try_assign_typed_ref_ex(zend_reference *ref, zval *val, zend_bool strict) /* {{{ */
+{
+ if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, val, strict))) {
+ zval_ptr_dtor(val);
+ return FAILURE;
+ } else {
+ zval_ptr_dtor(&ref->val);
+ ZVAL_COPY_VALUE(&ref->val, val);
+ return SUCCESS;
+ }
+}
+/* }}} */
+
+ZEND_API int zend_try_assign_typed_ref(zend_reference *ref, zval *val) /* {{{ */
+{
+ return zend_try_assign_typed_ref_ex(ref, val, ZEND_ARG_USES_STRICT_TYPES());
+}
+/* }}} */
+
+ZEND_API int zend_try_assign_typed_ref_null(zend_reference *ref) /* {{{ */
+{
+ zval tmp;
+
+ ZVAL_NULL(&tmp);
+ return zend_try_assign_typed_ref(ref, &tmp);
+}
+/* }}} */
+
+ZEND_API int zend_try_assign_typed_ref_bool(zend_reference *ref, zend_bool val) /* {{{ */
+{
+ zval tmp;
+
+ ZVAL_BOOL(&tmp, val);
+ return zend_try_assign_typed_ref(ref, &tmp);
+}
+/* }}} */
+
+ZEND_API int zend_try_assign_typed_ref_long(zend_reference *ref, zend_long lval) /* {{{ */
+{
+ zval tmp;
+
+ ZVAL_LONG(&tmp, lval);
+ return zend_try_assign_typed_ref(ref, &tmp);
+}
+/* }}} */
+
+ZEND_API int zend_try_assign_typed_ref_double(zend_reference *ref, double dval) /* {{{ */
+{
+ zval tmp;
+
+ ZVAL_DOUBLE(&tmp, dval);
+ return zend_try_assign_typed_ref(ref, &tmp);
+}
+/* }}} */
+
+ZEND_API int zend_try_assign_typed_ref_empty_string(zend_reference *ref) /* {{{ */
+{
+ zval tmp;
+
+ ZVAL_EMPTY_STRING(&tmp);
+ return zend_try_assign_typed_ref(ref, &tmp);
+}
+/* }}} */
+
+ZEND_API int zend_try_assign_typed_ref_str(zend_reference *ref, zend_string *str) /* {{{ */
+{
+ zval tmp;
+
+ ZVAL_STR(&tmp, str);
+ return zend_try_assign_typed_ref(ref, &tmp);
+}
+/* }}} */
+
+ZEND_API int zend_try_assign_typed_ref_string(zend_reference *ref, const char *string) /* {{{ */
+{
+ zval tmp;
+
+ ZVAL_STRING(&tmp, string);
+ return zend_try_assign_typed_ref(ref, &tmp);
+}
+/* }}} */
+
+ZEND_API int zend_try_assign_typed_ref_stringl(zend_reference *ref, const char *string, size_t len) /* {{{ */
+{
+ zval tmp;
+
+ ZVAL_STRINGL(&tmp, string, len);
+ return zend_try_assign_typed_ref(ref, &tmp);
+}
+/* }}} */
+
+ZEND_API int zend_try_assign_typed_ref_arr(zend_reference *ref, zend_array *arr) /* {{{ */
+{
+ zval tmp;
+
+ ZVAL_ARR(&tmp, arr);
+ return zend_try_assign_typed_ref(ref, &tmp);
+}
+/* }}} */
+
+ZEND_API int zend_try_assign_typed_ref_res(zend_reference *ref, zend_resource *res) /* {{{ */
+{
+ zval tmp;
+
+ ZVAL_RES(&tmp, res);
+ return zend_try_assign_typed_ref(ref, &tmp);
+}
+/* }}} */
+
+ZEND_API int zend_try_assign_typed_ref_zval(zend_reference *ref, zval *zv) /* {{{ */
+{
+ zval tmp;
+
+ ZVAL_COPY_VALUE(&tmp, zv);
+ return zend_try_assign_typed_ref(ref, &tmp);
+}
+/* }}} */
+
+ZEND_API int zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval *zv, zend_bool strict) /* {{{ */
+{
+ zval tmp;
+
+ ZVAL_COPY_VALUE(&tmp, zv);
+ return zend_try_assign_typed_ref_ex(ref, &tmp, strict);
+}
+/* }}} */
+
+ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment) /* {{{ */
+{
+ return zend_declare_typed_property(ce, name, property, access_type, doc_comment, 0);
+}
+/* }}} */
+
ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, size_t name_length, zval *property, int access_type) /* {{{ */
{
zend_string *key = zend_string_init(name, name_length, ce->type & ZEND_INTERNAL_CLASS);
@@ -3956,9 +4008,6 @@ ZEND_API void zend_update_property_ex(zend_class_entry *scope, zval *object, zen
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", ZSTR_VAL(name), ZSTR_VAL(Z_OBJCE_P(object)->name));
- }
ZVAL_STR(&property, name);
Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL);
@@ -3973,9 +4022,6 @@ ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const
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));
- }
ZVAL_STRINGL(&property, name, name_length);
Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL);
zval_ptr_dtor(&property);
@@ -4000,9 +4046,6 @@ ZEND_API void zend_unset_property(zend_class_entry *scope, zval *object, const c
EG(fake_scope) = scope;
- if (!Z_OBJ_HT_P(object)->unset_property) {
- zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be unset", name, ZSTR_VAL(Z_OBJCE_P(object)->name));
- }
ZVAL_STRINGL(&property, name, name_length);
Z_OBJ_HT_P(object)->unset_property(object, &property, 0);
zval_ptr_dtor(&property);
@@ -4069,25 +4112,30 @@ ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object
ZEND_API int zend_update_static_property_ex(zend_class_entry *scope, zend_string *name, zval *value) /* {{{ */
{
- zval *property;
+ zval *property, tmp;
+ zend_property_info *prop_info;
zend_class_entry *old_scope = EG(fake_scope);
EG(fake_scope) = scope;
- property = zend_std_get_static_property(scope, name, 0);
+ property = zend_std_get_static_property_with_info(scope, name, BP_VAR_W, &prop_info);
EG(fake_scope) = old_scope;
if (!property) {
return FAILURE;
}
- if (property != value) {
- zval garbage;
- ZVAL_DEREF(property);
- ZVAL_DEREF(value);
- ZVAL_COPY_VALUE(&garbage, property);
- ZVAL_COPY(property, value);
- zval_ptr_dtor(&garbage);
+ ZEND_ASSERT(!Z_ISREF_P(value));
+ Z_TRY_ADDREF_P(value);
+ if (prop_info->type) {
+ ZVAL_COPY_VALUE(&tmp, value);
+ if (!zend_verify_property_type(prop_info, &tmp, /* strict */ 0)) {
+ Z_TRY_DELREF_P(value);
+ return FAILURE;
+ }
+ value = &tmp;
}
+
+ zend_assign_to_variable(property, value, IS_TMP_VAR, /* strict */ 0);
return SUCCESS;
}
/* }}} */
@@ -4164,10 +4212,6 @@ ZEND_API zval *zend_read_property_ex(zend_class_entry *scope, zval *object, zend
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", ZSTR_VAL(name), ZSTR_VAL(Z_OBJCE_P(object)->name));
- }
-
ZVAL_STR(&property, name);
value = Z_OBJ_HT_P(object)->read_property(object, &property, silent?BP_VAR_IS:BP_VAR_R, NULL, rv);
@@ -4194,7 +4238,7 @@ ZEND_API zval *zend_read_static_property_ex(zend_class_entry *scope, zend_string
zend_class_entry *old_scope = EG(fake_scope);
EG(fake_scope) = scope;
- property = zend_std_get_static_property(scope, name, silent);
+ property = zend_std_get_static_property(scope, name, silent ? BP_VAR_IS : BP_VAR_R);
EG(fake_scope) = old_scope;
return property;