diff options
Diffstat (limited to 'Zend/zend_API.c')
-rw-r--r-- | Zend/zend_API.c | 508 |
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; |