diff options
Diffstat (limited to 'Zend/zend_object_handlers.c')
| -rw-r--r-- | Zend/zend_object_handlers.c | 203 |
1 files changed, 83 insertions, 120 deletions
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 65aefb6aec..f60083d858 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -104,10 +104,8 @@ ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */ } /* }}} */ -ZEND_API HashTable *zend_std_get_properties(zval *object) /* {{{ */ +ZEND_API HashTable *zend_std_get_properties(zend_object *zobj) /* {{{ */ { - zend_object *zobj; - zobj = Z_OBJ_P(object); if (!zobj->properties) { rebuild_object_properties(zobj); } @@ -115,15 +113,13 @@ ZEND_API HashTable *zend_std_get_properties(zval *object) /* {{{ */ } /* }}} */ -ZEND_API HashTable *zend_std_get_gc(zval *object, zval **table, int *n) /* {{{ */ +ZEND_API HashTable *zend_std_get_gc(zend_object *zobj, zval **table, int *n) /* {{{ */ { - if (Z_OBJ_HANDLER_P(object, get_properties) != zend_std_get_properties) { + if (zobj->handlers->get_properties != zend_std_get_properties) { *table = NULL; *n = 0; - return Z_OBJ_HANDLER_P(object, get_properties)(object); + return zobj->handlers->get_properties(zobj); } else { - zend_object *zobj = Z_OBJ_P(object); - if (zobj->properties) { *table = NULL; *n = 0; @@ -142,15 +138,15 @@ ZEND_API HashTable *zend_std_get_gc(zval *object, zval **table, int *n) /* {{{ * } /* }}} */ -ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp) /* {{{ */ +ZEND_API HashTable *zend_std_get_debug_info(zend_object *object, int *is_temp) /* {{{ */ { - zend_class_entry *ce = Z_OBJCE_P(object); + zend_class_entry *ce = object->ce; zval retval; HashTable *ht; if (!ce->__debugInfo) { *is_temp = 0; - return Z_OBJ_HANDLER_P(object, get_properties)(object); + return object->handlers->get_properties(object); } zend_call_method_with_0_params(object, ce, &ce->__debugInfo, ZEND_DEBUGINFO_FUNC_NAME, &retval); @@ -458,7 +454,7 @@ found: } offset = property_info->offset; - if (EXPECTED(!property_info->type)) { + if (EXPECTED(!ZEND_TYPE_IS_SET(property_info->type))) { property_info = NULL; } else { *info_ptr = property_info; @@ -652,23 +648,16 @@ ZEND_API uint32_t *zend_get_property_guard(zend_object *zobj, zend_string *membe } /* }}} */ -ZEND_API zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv) /* {{{ */ +ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int type, void **cache_slot, zval *rv) /* {{{ */ { - zend_object *zobj; - zend_string *name, *tmp_name; zval *retval; uintptr_t property_offset; zend_property_info *prop_info = NULL; uint32_t *guard = NULL; - - zobj = Z_OBJ_P(object); - name = zval_try_get_tmp_string(member, &tmp_name); - if (UNEXPECTED(!name)) { - return &EG(uninitialized_zval); - } + zend_string *tmp_name = NULL; #if DEBUG_OBJECT_HANDLERS - fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), ZSTR_VAL(name)); + fprintf(stderr, "Read object #%d property: %s\n", zobj->handle, ZSTR_VAL(name)); #endif /* make zend_get_property_info silent if we have getter - we may want to use it */ @@ -800,21 +789,13 @@ exit: } /* }}} */ -ZEND_API zval *zend_std_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */ +ZEND_API zval *zend_std_write_property(zend_object *zobj, zend_string *name, zval *value, void **cache_slot) /* {{{ */ { - zend_object *zobj; - zend_string *name, *tmp_name; zval *variable_ptr, tmp; uintptr_t property_offset; zend_property_info *prop_info = NULL; ZEND_ASSERT(!Z_ISREF_P(value)); - zobj = Z_OBJ_P(object); - name = zval_try_get_tmp_string(member, &tmp_name); - if (UNEXPECTED(!name)) { - return value; - } - property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__set != NULL), cache_slot, &prop_info); if (EXPECTED(IS_VALID_PROPERTY_OFFSET(property_offset))) { @@ -902,7 +883,6 @@ write_std_property: } exit: - zend_tmp_string_release(tmp_name); return variable_ptr; } /* }}} */ @@ -913,10 +893,10 @@ static ZEND_COLD zend_never_inline void zend_bad_array_access(zend_class_entry * } /* }}} */ -ZEND_API zval *zend_std_read_dimension(zval *object, zval *offset, int type, zval *rv) /* {{{ */ +ZEND_API zval *zend_std_read_dimension(zend_object *object, zval *offset, int type, zval *rv) /* {{{ */ { - zend_class_entry *ce = Z_OBJCE_P(object); - zval tmp_offset, tmp_object; + zend_class_entry *ce = object->ce; + zval tmp_offset; if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) { if (offset == NULL) { @@ -926,17 +906,16 @@ ZEND_API zval *zend_std_read_dimension(zval *object, zval *offset, int type, zva ZVAL_COPY_DEREF(&tmp_offset, offset); } - Z_ADDREF_P(object); - ZVAL_OBJ(&tmp_object, Z_OBJ_P(object)); + GC_ADDREF(object); if (type == BP_VAR_IS) { - zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetexists", rv, &tmp_offset); + zend_call_method_with_1_params(object, ce, NULL, "offsetexists", rv, &tmp_offset); if (UNEXPECTED(Z_ISUNDEF_P(rv))) { - zval_ptr_dtor(&tmp_object); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); return NULL; } if (!i_zend_is_true(rv)) { - zval_ptr_dtor(&tmp_object); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); zval_ptr_dtor(rv); return &EG(uninitialized_zval); @@ -944,9 +923,9 @@ ZEND_API zval *zend_std_read_dimension(zval *object, zval *offset, int type, zva zval_ptr_dtor(rv); } - zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetget", rv, &tmp_offset); + zend_call_method_with_1_params(object, ce, NULL, "offsetget", rv, &tmp_offset); - zval_ptr_dtor(&tmp_object); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); if (UNEXPECTED(Z_TYPE_P(rv) == IS_UNDEF)) { @@ -963,10 +942,10 @@ ZEND_API zval *zend_std_read_dimension(zval *object, zval *offset, int type, zva } /* }}} */ -ZEND_API void zend_std_write_dimension(zval *object, zval *offset, zval *value) /* {{{ */ +ZEND_API void zend_std_write_dimension(zend_object *object, zval *offset, zval *value) /* {{{ */ { - zend_class_entry *ce = Z_OBJCE_P(object); - zval tmp_offset, tmp_object; + zend_class_entry *ce = object->ce; + zval tmp_offset; if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) { if (!offset) { @@ -974,10 +953,9 @@ ZEND_API void zend_std_write_dimension(zval *object, zval *offset, zval *value) } else { ZVAL_COPY_DEREF(&tmp_offset, offset); } - Z_ADDREF_P(object); - ZVAL_OBJ(&tmp_object, Z_OBJ_P(object)); - zend_call_method_with_2_params(&tmp_object, ce, NULL, "offsetset", NULL, &tmp_offset, value); - zval_ptr_dtor(&tmp_object); + GC_ADDREF(object); + zend_call_method_with_2_params(object, ce, NULL, "offsetset", NULL, &tmp_offset, value); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); } else { zend_bad_array_access(ce); @@ -985,25 +963,24 @@ ZEND_API void zend_std_write_dimension(zval *object, zval *offset, zval *value) } /* }}} */ -ZEND_API int zend_std_has_dimension(zval *object, zval *offset, int check_empty) /* {{{ */ +ZEND_API int zend_std_has_dimension(zend_object *object, zval *offset, int check_empty) /* {{{ */ { - zend_class_entry *ce = Z_OBJCE_P(object); - zval retval, tmp_offset, tmp_object; + zend_class_entry *ce = object->ce; + zval retval, tmp_offset; int result; if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) { ZVAL_COPY_DEREF(&tmp_offset, offset); - Z_ADDREF_P(object); - ZVAL_OBJ(&tmp_object, Z_OBJ_P(object)); - zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetexists", &retval, &tmp_offset); + GC_ADDREF(object); + zend_call_method_with_1_params(object, ce, NULL, "offsetexists", &retval, &tmp_offset); result = i_zend_is_true(&retval); zval_ptr_dtor(&retval); if (check_empty && result && EXPECTED(!EG(exception))) { - zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetget", &retval, &tmp_offset); + zend_call_method_with_1_params(object, ce, NULL, "offsetget", &retval, &tmp_offset); result = i_zend_is_true(&retval); zval_ptr_dtor(&retval); } - zval_ptr_dtor(&tmp_object); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); } else { zend_bad_array_access(ce); @@ -1013,22 +990,14 @@ ZEND_API int zend_std_has_dimension(zval *object, zval *offset, int check_empty) } /* }}} */ -ZEND_API zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot) /* {{{ */ +ZEND_API zval *zend_std_get_property_ptr_ptr(zend_object *zobj, zend_string *name, int type, void **cache_slot) /* {{{ */ { - zend_object *zobj; - zend_string *name, *tmp_name; zval *retval = NULL; uintptr_t property_offset; zend_property_info *prop_info = NULL; - zobj = Z_OBJ_P(object); - name = zval_try_get_tmp_string(member, &tmp_name); - if (UNEXPECTED(!name)) { - return NULL; - } - #if DEBUG_OBJECT_HANDLERS - fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), ZSTR_VAL(name)); + fprintf(stderr, "Ptr object #%d property: %s\n", object->handle, ZSTR_VAL(name)); #endif property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__get != NULL), cache_slot, &prop_info); @@ -1056,7 +1025,6 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int typ zobj->properties = zend_array_dup(zobj->properties); } if (EXPECTED((retval = zend_hash_find(zobj->properties, name)) != NULL)) { - zend_tmp_string_release(tmp_name); return retval; } } @@ -1074,24 +1042,15 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int typ } } - zend_tmp_string_release(tmp_name); return retval; } /* }}} */ -ZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_slot) /* {{{ */ +ZEND_API void zend_std_unset_property(zend_object *zobj, zend_string *name, void **cache_slot) /* {{{ */ { - zend_object *zobj; - zend_string *name, *tmp_name; uintptr_t property_offset; zend_property_info *prop_info = NULL; - zobj = Z_OBJ_P(object); - name = zval_try_get_tmp_string(member, &tmp_name); - if (UNEXPECTED(!name)) { - return; - } - property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__unset != NULL), cache_slot, &prop_info); if (EXPECTED(IS_VALID_PROPERTY_OFFSET(property_offset))) { @@ -1109,7 +1068,7 @@ ZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_s if (zobj->properties) { HT_FLAGS(zobj->properties) |= HASH_FLAG_HAS_EMPTY_IND; } - goto exit; + return; } } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(property_offset)) && EXPECTED(zobj->properties != NULL)) { @@ -1120,10 +1079,10 @@ ZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_s zobj->properties = zend_array_dup(zobj->properties); } if (EXPECTED(zend_hash_del(zobj->properties, name) != FAILURE)) { - goto exit; + return; } } else if (UNEXPECTED(EG(exception))) { - goto exit; + return; } /* magic unset */ @@ -1138,28 +1097,24 @@ ZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_s /* Trigger the correct error */ zend_wrong_offset(zobj->ce, name); ZEND_ASSERT(EG(exception)); - goto exit; + return; } else { /* Nothing to do: The property already does not exist. */ } } - -exit: - zend_tmp_string_release(tmp_name); } /* }}} */ -ZEND_API void zend_std_unset_dimension(zval *object, zval *offset) /* {{{ */ +ZEND_API void zend_std_unset_dimension(zend_object *object, zval *offset) /* {{{ */ { - zend_class_entry *ce = Z_OBJCE_P(object); - zval tmp_offset, tmp_object; + zend_class_entry *ce = object->ce; + zval tmp_offset; if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1)) { ZVAL_COPY_DEREF(&tmp_offset, offset); - Z_ADDREF_P(object); - ZVAL_OBJ(&tmp_object, Z_OBJ_P(object)); - zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetunset", NULL, &tmp_offset); - zval_ptr_dtor(&tmp_object); + GC_ADDREF(object); + zend_call_method_with_1_params(object, ce, NULL, "offsetunset", NULL, &tmp_offset); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); } else { zend_bad_array_access(ce); @@ -1279,6 +1234,13 @@ static ZEND_COLD zend_never_inline void zend_bad_method_call(zend_function *fbc, } /* }}} */ +static ZEND_COLD zend_never_inline void zend_abstract_method_call(zend_function *fbc) /* {{{ */ +{ + zend_throw_error(NULL, "Cannot call abstract method %s::%s()", + ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name)); +} +/* }}} */ + ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *method_name, const zval *key) /* {{{ */ { zend_object *zobj = *obj_ptr; @@ -1339,6 +1301,10 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string * } exit: + if (fbc && UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_ABSTRACT)) { + zend_abstract_method_call(fbc); + fbc = NULL; + } if (UNEXPECTED(!key)) { ZSTR_ALLOCA_FREE(lc_method_name, use_heap); } @@ -1424,6 +1390,11 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st } } + if (fbc && UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_ABSTRACT)) { + zend_abstract_method_call(fbc); + fbc = NULL; + } + if (UNEXPECTED(!key)) { zend_string_release_ex(lc_function_name, 0); } @@ -1511,7 +1482,7 @@ undeclared_property: ZVAL_DEINDIRECT(ret); if (UNEXPECTED((type == BP_VAR_R || type == BP_VAR_RW) - && Z_TYPE_P(ret) == IS_UNDEF && property_info->type != 0)) { + && Z_TYPE_P(ret) == IS_UNDEF && ZEND_TYPE_IS_SET(property_info->type))) { zend_throw_error(NULL, "Typed static property %s::$%s must not be accessed before initialization", ZSTR_VAL(property_info->ce->name), zend_get_unmangled_property_name(property_name)); @@ -1647,20 +1618,13 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */ } /* }}} */ -ZEND_API int zend_std_has_property(zval *object, zval *member, int has_set_exists, void **cache_slot) /* {{{ */ +ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has_set_exists, void **cache_slot) /* {{{ */ { - zend_object *zobj; int result; zval *value = NULL; - zend_string *name, *tmp_name; uintptr_t property_offset; zend_property_info *prop_info = NULL; - - zobj = Z_OBJ_P(object); - name = zval_try_get_tmp_string(member, &tmp_name); - if (UNEXPECTED(!name)) { - return 0; - } + zend_string *tmp_name = NULL; property_offset = zend_get_property_offset(zobj->ce, name, 1, cache_slot, &prop_info); @@ -1757,14 +1721,14 @@ ZEND_API zend_string *zend_std_get_class_name(const zend_object *zobj) /* {{{ */ } /* }}} */ -ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type) /* {{{ */ +ZEND_API int zend_std_cast_object_tostring(zend_object *readobj, zval *writeobj, int type) /* {{{ */ { zval retval; zend_class_entry *ce; switch (type) { case IS_STRING: - ce = Z_OBJCE_P(readobj); + ce = readobj->ce; if (ce->__tostring) { zend_call_method_with_0_params(readobj, ce, &ce->__tostring, "__tostring", &retval); if (EXPECTED(Z_TYPE(retval) == IS_STRING)) { @@ -1781,17 +1745,17 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty ZVAL_TRUE(writeobj); return SUCCESS; case IS_LONG: - ce = Z_OBJCE_P(readobj); + ce = readobj->ce; zend_error(E_NOTICE, "Object of class %s could not be converted to int", ZSTR_VAL(ce->name)); ZVAL_LONG(writeobj, 1); return SUCCESS; case IS_DOUBLE: - ce = Z_OBJCE_P(readobj); + ce = readobj->ce; zend_error(E_NOTICE, "Object of class %s could not be converted to float", ZSTR_VAL(ce->name)); ZVAL_DOUBLE(writeobj, 1); return SUCCESS; case _IS_NUMBER: - ce = Z_OBJCE_P(readobj); + ce = readobj->ce; zend_error(E_NOTICE, "Object of class %s could not be converted to number", ZSTR_VAL(ce->name)); ZVAL_LONG(writeobj, 1); return SUCCESS; @@ -1803,10 +1767,10 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty } /* }}} */ -ZEND_API int zend_std_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr) /* {{{ */ +ZEND_API int zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, zend_bool check_only) /* {{{ */ { zval *func; - zend_class_entry *ce = Z_OBJCE_P(obj); + zend_class_entry *ce = obj->ce; if ((func = zend_hash_find_ex(&ce->function_table, ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE), 1)) == NULL) { return FAILURE; @@ -1820,20 +1784,20 @@ ZEND_API int zend_std_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_fun } } else { if (obj_ptr) { - *obj_ptr = Z_OBJ_P(obj); + *obj_ptr = obj; } } return SUCCESS; } /* }}} */ -ZEND_API HashTable *zend_std_get_properties_for(zval *obj, zend_prop_purpose purpose) { +ZEND_API HashTable *zend_std_get_properties_for(zend_object *obj, zend_prop_purpose purpose) { HashTable *ht; switch (purpose) { case ZEND_PROP_PURPOSE_DEBUG: - if (Z_OBJ_HT_P(obj)->get_debug_info) { + if (obj->handlers->get_debug_info) { int is_temp; - ht = Z_OBJ_HT_P(obj)->get_debug_info(obj, &is_temp); + ht = obj->handlers->get_debug_info(obj, &is_temp); if (ht && !is_temp && !(GC_FLAGS(ht) & GC_IMMUTABLE)) { GC_ADDREF(ht); } @@ -1845,7 +1809,7 @@ ZEND_API HashTable *zend_std_get_properties_for(zval *obj, zend_prop_purpose pur case ZEND_PROP_PURPOSE_VAR_EXPORT: case ZEND_PROP_PURPOSE_JSON: case _ZEND_PROP_PURPOSE_ARRAY_KEY_EXISTS: - ht = Z_OBJ_HT_P(obj)->get_properties(obj); + ht = obj->handlers->get_properties(obj); if (ht && !(GC_FLAGS(ht) & GC_IMMUTABLE)) { GC_ADDREF(ht); } @@ -1857,11 +1821,13 @@ ZEND_API HashTable *zend_std_get_properties_for(zval *obj, zend_prop_purpose pur } ZEND_API HashTable *zend_get_properties_for(zval *obj, zend_prop_purpose purpose) { - if (Z_OBJ_HT_P(obj)->get_properties_for) { - return Z_OBJ_HT_P(obj)->get_properties_for(obj, purpose); + zend_object *zobj = Z_OBJ_P(obj); + + if (zobj->handlers->get_properties_for) { + return zobj->handlers->get_properties_for(zobj, purpose); } - return zend_std_get_properties_for(obj, purpose); + return zend_std_get_properties_for(zobj, purpose); } ZEND_API const zend_object_handlers std_object_handlers = { @@ -1876,15 +1842,12 @@ ZEND_API const zend_object_handlers std_object_handlers = { zend_std_read_dimension, /* read_dimension */ zend_std_write_dimension, /* write_dimension */ zend_std_get_property_ptr_ptr, /* get_property_ptr_ptr */ - NULL, /* get */ - NULL, /* set */ zend_std_has_property, /* has_property */ zend_std_unset_property, /* unset_property */ zend_std_has_dimension, /* has_dimension */ zend_std_unset_dimension, /* unset_dimension */ zend_std_get_properties, /* get_properties */ zend_std_get_method, /* get_method */ - NULL, /* call_method */ zend_std_get_constructor, /* get_constructor */ zend_std_get_class_name, /* get_class_name */ zend_std_compare_objects, /* compare_objects */ |
