1637a4042SMarcus Boerger/*
2333406bdSfoobar   +----------------------------------------------------------------------+
3333406bdSfoobar   | Zend Engine                                                          |
4333406bdSfoobar   +----------------------------------------------------------------------+
5a6519d05SXinchen Hui   | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
6333406bdSfoobar   +----------------------------------------------------------------------+
7333406bdSfoobar   | This source file is subject to version 2.00 of the Zend license,     |
8333406bdSfoobar   | that is bundled with this package in the file LICENSE, and is        |
9f68c7ff2SJames Cox   | available through the world-wide-web at the following url:           |
10333406bdSfoobar   | http://www.zend.com/license/2_00.txt.                                |
11333406bdSfoobar   | If you did not receive a copy of the Zend license and are unable to  |
12333406bdSfoobar   | obtain it through the world-wide-web, please send a note to          |
13333406bdSfoobar   | license@zend.com so we can mail you a copy immediately.              |
14333406bdSfoobar   +----------------------------------------------------------------------+
159afce019SZeev Suraski   | Authors: Andi Gutmans <andi@php.net>                                 |
169afce019SZeev Suraski   |          Zeev Suraski <zeev@php.net>                                 |
179afce019SZeev Suraski   |          Dmitry Stogov <dmitry@php.net>                              |
18333406bdSfoobar   +----------------------------------------------------------------------+
216608f073SStanislav Malyshev#include "zend.h"
226608f073SStanislav Malyshev#include "zend_globals.h"
236608f073SStanislav Malyshev#include "zend_variables.h"
246608f073SStanislav Malyshev#include "zend_API.h"
256608f073SStanislav Malyshev#include "zend_objects.h"
26f75f3cffSStanislav Malyshev#include "zend_objects_API.h"
276608f073SStanislav Malyshev#include "zend_object_handlers.h"
284dba05d9SMarcus Boerger#include "zend_interfaces.h"
295a99c07eSAaron Piotrowski#include "zend_exceptions.h"
30f90255c6SEtienne Kneuss#include "zend_closures.h"
318e3aebd5SScott MacVicar#include "zend_compile.h"
324411641bSKalle Sommer Nielsen#include "zend_hash.h"
336608f073SStanislav Malyshev
3400e90f2fSAndi Gutmans#define DEBUG_OBJECT_HANDLERS 0
356608f073SStanislav Malyshev
360fb05f14SDmitry Stogov#define ZEND_WRONG_PROPERTY_OFFSET   0
370fb05f14SDmitry Stogov
38f4cfaf36SDmitry Stogov/* guard flags */
39f4cfaf36SDmitry Stogov#define IN_GET		(1<<0)
40f4cfaf36SDmitry Stogov#define IN_SET		(1<<1)
41f4cfaf36SDmitry Stogov#define IN_UNSET	(1<<2)
42f4cfaf36SDmitry Stogov#define IN_ISSET	(1<<3)
431b355e11SStanislav Malyshev
44d8651c82SStanislav Malyshev/*
45d8651c82SStanislav Malyshev  __X accessors explanation:
46d8651c82SStanislav Malyshev
47d8651c82SStanislav Malyshev  if we have __get and property that is not part of the properties array is
48d8651c82SStanislav Malyshev  requested, we call __get handler. If it fails, we return uninitialized.
49d8651c82SStanislav Malyshev
50d8651c82SStanislav Malyshev  if we have __set and property that is not part of the properties array is
51d8651c82SStanislav Malyshev  set, we call __set handler. If it fails, we do not change the array.
52d8651c82SStanislav Malyshev
53d8651c82SStanislav Malyshev  for both handlers above, when we are inside __get/__set, no further calls for
548ce1211aSMarcus Boerger  __get/__set for this property of this object will be made, to prevent endless
55008259dbSStanislav Malyshev  recursion and enable accessors to change properties array.
56d8651c82SStanislav Malyshev
57d8651c82SStanislav Malyshev  if we have __call and method which is not part of the class function table is
58637a4042SMarcus Boerger  called, we cal __call handler.
59d8651c82SStanislav Malyshev*/
60d8651c82SStanislav Malyshev
61c5237d82SDmitry StogovZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
62c5237d82SDmitry Stogov{
63c5237d82SDmitry Stogov	if (!zobj->properties) {
64c5237d82SDmitry Stogov		zend_property_info *prop_info;
65c5237d82SDmitry Stogov		zend_class_entry *ce = zobj->ce;
66c5237d82SDmitry Stogov
6744e0b79aSDmitry Stogov		zobj->properties = zend_new_array(ce->default_properties_count);
68c5237d82SDmitry Stogov		if (ce->default_properties_count) {
69a795bd82SDmitry Stogov			zend_hash_real_init_mixed(zobj->properties);
707652a977SDmitry Stogov			ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
71c5237d82SDmitry Stogov				if (/*prop_info->ce == ce &&*/
7225f9e255SDmitry Stogov				    (prop_info->flags & ZEND_ACC_STATIC) == 0) {
7325f9e255SDmitry Stogov
7425f9e255SDmitry Stogov					if (UNEXPECTED(Z_TYPE_P(OBJ_PROP(zobj, prop_info->offset)) == IS_UNDEF)) {
756634d5e3SDmitry Stogov						HT_FLAGS(zobj->properties) |= HASH_FLAG_HAS_EMPTY_IND;
7625f9e255SDmitry Stogov					}
77887189caSDmitry Stogov
7864002648SGabriel Caruso					_zend_hash_append_ind(zobj->properties, prop_info->name,
799f9ffdd0SDmitry Stogov						OBJ_PROP(zobj, prop_info->offset));
80a0dff6fdSStanislav Malyshev				}
817652a977SDmitry Stogov			} ZEND_HASH_FOREACH_END();
82c5237d82SDmitry Stogov			while (ce->parent && ce->parent->default_properties_count) {
83c5237d82SDmitry Stogov				ce = ce->parent;
847652a977SDmitry Stogov				ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
85c5237d82SDmitry Stogov					if (prop_info->ce == ce &&
86a0dff6fdSStanislav Malyshev					    (prop_info->flags & ZEND_ACC_STATIC) == 0 &&
8725f9e255SDmitry Stogov					    (prop_info->flags & ZEND_ACC_PRIVATE) != 0) {
88887189caSDmitry Stogov						zval zv;
89b7a7b1a6SStanislav Malyshev
9025f9e255SDmitry Stogov						if (UNEXPECTED(Z_TYPE_P(OBJ_PROP(zobj, prop_info->offset)) == IS_UNDEF)) {
916634d5e3SDmitry Stogov							HT_FLAGS(zobj->properties) |= HASH_FLAG_HAS_EMPTY_IND;
9225f9e255SDmitry Stogov						}
9325f9e255SDmitry Stogov
9475041379SDmitry Stogov						ZVAL_INDIRECT(&zv, OBJ_PROP(zobj, prop_info->offset));
95887189caSDmitry Stogov						zend_hash_add(zobj->properties, prop_info->name, &zv);
96a0dff6fdSStanislav Malyshev					}
977652a977SDmitry Stogov				} ZEND_HASH_FOREACH_END();
98c5237d82SDmitry Stogov			}
99c5237d82SDmitry Stogov		}
100c5237d82SDmitry Stogov	}
101c5237d82SDmitry Stogov}
102c2a92317SEtienne Kneuss/* }}} */
103c5237d82SDmitry Stogov
104bdeb220fSAnatol BelskiZEND_API HashTable *zend_std_get_properties(zval *object) /* {{{ */
1056608f073SStanislav Malyshev{
1066608f073SStanislav Malyshev	zend_object *zobj;
1076ac6cb10SHarald Radi	zobj = Z_OBJ_P(object);
108c5237d82SDmitry Stogov	if (!zobj->properties) {
109c5237d82SDmitry Stogov		rebuild_object_properties(zobj);
110c5237d82SDmitry Stogov	}
1116608f073SStanislav Malyshev	return zobj->properties;
1126608f073SStanislav Malyshev}
113b4892511SJani Taskinen/* }}} */
114b4892511SJani Taskinen
115bdeb220fSAnatol BelskiZEND_API HashTable *zend_std_get_gc(zval *object, zval **table, int *n) /* {{{ */
116e0f781f4SDmitry Stogov{
117e0f781f4SDmitry Stogov	if (Z_OBJ_HANDLER_P(object, get_properties) != zend_std_get_properties) {
118e0f781f4SDmitry Stogov		*table = NULL;
119e0f781f4SDmitry Stogov		*n = 0;
120bdeb220fSAnatol Belski		return Z_OBJ_HANDLER_P(object, get_properties)(object);
121e0f781f4SDmitry Stogov	} else {
122e0f781f4SDmitry Stogov		zend_object *zobj = Z_OBJ_P(object);
123e0f781f4SDmitry Stogov
1242a9f9860SDmitry Stogov		if (zobj->properties) {
1252a9f9860SDmitry Stogov			*table = NULL;
1262a9f9860SDmitry Stogov			*n = 0;
127358379beSDmitry Stogov			if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)
128358379beSDmitry Stogov			 && EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
129bff2743cSDmitry Stogov				GC_DELREF(zobj->properties);
130358379beSDmitry Stogov				zobj->properties = zend_array_dup(zobj->properties);
131358379beSDmitry Stogov			}
1322a9f9860SDmitry Stogov			return zobj->properties;
1332a9f9860SDmitry Stogov		} else {
1342a9f9860SDmitry Stogov			*table = zobj->properties_table;
1352a9f9860SDmitry Stogov			*n = zobj->ce->default_properties_count;
1362a9f9860SDmitry Stogov			return NULL;
1372a9f9860SDmitry Stogov		}
138e0f781f4SDmitry Stogov	}
139e0f781f4SDmitry Stogov}
140e0f781f4SDmitry Stogov/* }}} */
141e0f781f4SDmitry Stogov
142bdeb220fSAnatol BelskiZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp) /* {{{ */
143b4892511SJani Taskinen{
1441e752ce9SSara Golemon	zend_class_entry *ce = Z_OBJCE_P(object);
145f9927a6cSDmitry Stogov	zval retval;
146f9927a6cSDmitry Stogov	HashTable *ht;
1471e752ce9SSara Golemon
1481e752ce9SSara Golemon	if (!ce->__debugInfo) {
1491e752ce9SSara Golemon		*is_temp = 0;
1501e752ce9SSara Golemon		return Z_OBJ_HANDLER_P(object, get_properties)
151bdeb220fSAnatol Belski			? Z_OBJ_HANDLER_P(object, get_properties)(object)
1521e752ce9SSara Golemon			: NULL;
1531e752ce9SSara Golemon	}
1541e752ce9SSara Golemon
155f9927a6cSDmitry Stogov	zend_call_method_with_0_params(object, ce, &ce->__debugInfo, ZEND_DEBUGINFO_FUNC_NAME, &retval);
156f9927a6cSDmitry Stogov	if (Z_TYPE(retval) == IS_ARRAY) {
1573e9bb03aSDmitry Stogov		if (!Z_REFCOUNTED(retval)) {
158af78ea1dSDmitry Stogov			*is_temp = 1;
159e10e151eSDmitry Stogov			return zend_array_dup(Z_ARRVAL(retval));
160af78ea1dSDmitry Stogov		} else if (Z_REFCOUNT(retval) <= 1) {
1611e752ce9SSara Golemon			*is_temp = 1;
162927d68dbSDmitry Stogov			ht = Z_ARR(retval);
1631e752ce9SSara Golemon			return ht;
1641e752ce9SSara Golemon		} else {
1651e752ce9SSara Golemon			*is_temp = 0;
1661e752ce9SSara Golemon			zval_ptr_dtor(&retval);
167af78ea1dSDmitry Stogov			return Z_ARRVAL(retval);
1681e752ce9SSara Golemon		}
169f9927a6cSDmitry Stogov	} else if (Z_TYPE(retval) == IS_NULL) {
1701e752ce9SSara Golemon		*is_temp = 1;
17144e0b79aSDmitry Stogov		ht = zend_new_array(0);
172f9927a6cSDmitry Stogov		return ht;
1731e752ce9SSara Golemon	}
1741e752ce9SSara Golemon
175acfc31c0SDmitry Stogov	zend_error_noreturn(E_ERROR, ZEND_DEBUGINFO_FUNC_NAME "() must return an array");
17699d1a1bbSBob Weinand
17799d1a1bbSBob Weinand	return NULL; /* Compilers are dumb and don't understand that noreturn means that the function does NOT need a return value... */
178b4892511SJani Taskinen}
179b4892511SJani Taskinen/* }}} */
1806608f073SStanislav Malyshev
18157527455SDmitry Stogovstatic void zend_std_call_getter(zend_object *zobj, zend_string *prop_name, zval *retval) /* {{{ */
182d8651c82SStanislav Malyshev{
1834182b085SDmitry Stogov	zend_class_entry *ce = zobj->ce;
184e9c3f9fcSDmitry Stogov	zend_class_entry *orig_fake_scope = EG(fake_scope);
18534e58a64SDmitry Stogov	zend_fcall_info fci;
18634e58a64SDmitry Stogov	zend_fcall_info_cache fcic;
18757527455SDmitry Stogov	zval member;
188e9c3f9fcSDmitry Stogov
189e9c3f9fcSDmitry Stogov	EG(fake_scope) = NULL;
190637a4042SMarcus Boerger
191e39f3f3fSMarcus Boerger	/* __get handler is called with one argument:
192e39f3f3fSMarcus Boerger	      property name
193d8651c82SStanislav Malyshev
1944b953534SVeres Lajos	   it should return whether the call was successful or not
195d8651c82SStanislav Malyshev	*/
19634e58a64SDmitry Stogov
19757527455SDmitry Stogov	ZVAL_STR(&member, prop_name);
19857527455SDmitry Stogov
19934e58a64SDmitry Stogov	fci.size = sizeof(fci);
2004182b085SDmitry Stogov	fci.object = zobj;
20134e58a64SDmitry Stogov	fci.retval = retval;
20234e58a64SDmitry Stogov	fci.param_count = 1;
20357527455SDmitry Stogov	fci.params = &member;
20434e58a64SDmitry Stogov	fci.no_separation = 1;
20534e58a64SDmitry Stogov	ZVAL_UNDEF(&fci.function_name); /* Unused */
20634e58a64SDmitry Stogov
20734e58a64SDmitry Stogov	fcic.function_handler = ce->__get;
20834e58a64SDmitry Stogov	fcic.called_scope = ce;
2094182b085SDmitry Stogov	fcic.object = zobj;
21034e58a64SDmitry Stogov
21134e58a64SDmitry Stogov	zend_call_function(&fci, &fcic);
212d8651c82SStanislav Malyshev
213e9c3f9fcSDmitry Stogov	EG(fake_scope) = orig_fake_scope;
214d8651c82SStanislav Malyshev}
215b4892511SJani Taskinen/* }}} */
216d8651c82SStanislav Malyshev
21757527455SDmitry Stogovstatic void zend_std_call_setter(zend_object *zobj, zend_string *prop_name, zval *value) /* {{{ */
218d8651c82SStanislav Malyshev{
2194182b085SDmitry Stogov	zend_class_entry *ce = zobj->ce;
220e9c3f9fcSDmitry Stogov	zend_class_entry *orig_fake_scope = EG(fake_scope);
22134e58a64SDmitry Stogov	zend_fcall_info fci;
22234e58a64SDmitry Stogov	zend_fcall_info_cache fcic;
22334e58a64SDmitry Stogov	zval args[2], ret;
224e9c3f9fcSDmitry Stogov
225e9c3f9fcSDmitry Stogov	EG(fake_scope) = NULL;
226fd4fe1c8SDmitry Stogov
227d8651c82SStanislav Malyshev	/* __set handler is called with two arguments:
228e39f3f3fSMarcus Boerger	     property name
229e39f3f3fSMarcus Boerger	     value to be set
230d8651c82SStanislav Malyshev	*/
23134e58a64SDmitry Stogov
23257527455SDmitry Stogov	ZVAL_STR(&args[0], prop_name);
23334e58a64SDmitry Stogov	ZVAL_COPY_VALUE(&args[1], value);
23434e58a64SDmitry Stogov	ZVAL_UNDEF(&ret);
23534e58a64SDmitry Stogov
23634e58a64SDmitry Stogov	fci.size = sizeof(fci);
2374182b085SDmitry Stogov	fci.object = zobj;
23834e58a64SDmitry Stogov	fci.retval = &ret;
23934e58a64SDmitry Stogov	fci.param_count = 2;
24034e58a64SDmitry Stogov	fci.params = args;
24134e58a64SDmitry Stogov	fci.no_separation = 1;
24234e58a64SDmitry Stogov	ZVAL_UNDEF(&fci.function_name); /* Unused */
24334e58a64SDmitry Stogov
24434e58a64SDmitry Stogov	fcic.function_handler = ce->__set;
24534e58a64SDmitry Stogov	fcic.called_scope = ce;
2464182b085SDmitry Stogov	fcic.object = zobj;
24734e58a64SDmitry Stogov
24834e58a64SDmitry Stogov	zend_call_function(&fci, &fcic);
24934e58a64SDmitry Stogov	zval_ptr_dtor(&ret);
250d8651c82SStanislav Malyshev
2510806bb39SNikita Popov	EG(fake_scope) = orig_fake_scope;
252d8651c82SStanislav Malyshev}
253b4892511SJani Taskinen/* }}} */
254d8651c82SStanislav Malyshev
25557527455SDmitry Stogovstatic void zend_std_call_unsetter(zend_object *zobj, zend_string *prop_name) /* {{{ */
256345e0255SDmitry Stogov{
2574182b085SDmitry Stogov	zend_class_entry *ce = zobj->ce;
258e9c3f9fcSDmitry Stogov	zend_class_entry *orig_fake_scope = EG(fake_scope);
25934e58a64SDmitry Stogov	zend_fcall_info fci;
26034e58a64SDmitry Stogov	zend_fcall_info_cache fcic;
26157527455SDmitry Stogov	zval ret, member;
262e9c3f9fcSDmitry Stogov
263e9c3f9fcSDmitry Stogov	EG(fake_scope) = NULL;
264637a4042SMarcus Boerger
265345e0255SDmitry Stogov	/* __unset handler is called with one argument:
266345e0255SDmitry Stogov	      property name
267345e0255SDmitry Stogov	*/
268637a4042SMarcus Boerger
26957527455SDmitry Stogov	ZVAL_STR(&member, prop_name);
27034e58a64SDmitry Stogov	ZVAL_UNDEF(&ret);
27134e58a64SDmitry Stogov
27234e58a64SDmitry Stogov	fci.size = sizeof(fci);
2734182b085SDmitry Stogov	fci.object = zobj;
27434e58a64SDmitry Stogov	fci.retval = &ret;
27534e58a64SDmitry Stogov	fci.param_count = 1;
27657527455SDmitry Stogov	fci.params = &member;
27734e58a64SDmitry Stogov	fci.no_separation = 1;
27834e58a64SDmitry Stogov	ZVAL_UNDEF(&fci.function_name); /* Unused */
27934e58a64SDmitry Stogov
28034e58a64SDmitry Stogov	fcic.function_handler = ce->__unset;
28134e58a64SDmitry Stogov	fcic.called_scope = ce;
2824182b085SDmitry Stogov	fcic.object = zobj;
28334e58a64SDmitry Stogov
28434e58a64SDmitry Stogov	zend_call_function(&fci, &fcic);
28534e58a64SDmitry Stogov	zval_ptr_dtor(&ret);
286345e0255SDmitry Stogov
287e9c3f9fcSDmitry Stogov	EG(fake_scope) = orig_fake_scope;
288345e0255SDmitry Stogov}
289b4892511SJani Taskinen/* }}} */
290345e0255SDmitry Stogov
29157527455SDmitry Stogovstatic void zend_std_call_issetter(zend_object *zobj, zend_string *prop_name, zval *retval) /* {{{ */
292345e0255SDmitry Stogov{
2934182b085SDmitry Stogov	zend_class_entry *ce = zobj->ce;
294e9c3f9fcSDmitry Stogov	zend_class_entry *orig_fake_scope = EG(fake_scope);
29534e58a64SDmitry Stogov	zend_fcall_info fci;
29634e58a64SDmitry Stogov	zend_fcall_info_cache fcic;
29757527455SDmitry Stogov	zval member;
298e9c3f9fcSDmitry Stogov
299e9c3f9fcSDmitry Stogov	EG(fake_scope) = NULL;
300637a4042SMarcus Boerger
301345e0255SDmitry Stogov	/* __isset handler is called with one argument:
302345e0255SDmitry Stogov	      property name
303345e0255SDmitry Stogov
304345e0255SDmitry Stogov	   it should return whether the property is set or not
305345e0255SDmitry Stogov	*/
306637a4042SMarcus Boerger
30757527455SDmitry Stogov	ZVAL_STR(&member, prop_name);
30857527455SDmitry Stogov
30934e58a64SDmitry Stogov	fci.size = sizeof(fci);
3104182b085SDmitry Stogov	fci.object = zobj;
31134e58a64SDmitry Stogov	fci.retval = retval;
31234e58a64SDmitry Stogov	fci.param_count = 1;
31357527455SDmitry Stogov	fci.params = &member;
31434e58a64SDmitry Stogov	fci.no_separation = 1;
31534e58a64SDmitry Stogov	ZVAL_UNDEF(&fci.function_name); /* Unused */
31634e58a64SDmitry Stogov
31734e58a64SDmitry Stogov	fcic.function_handler = ce->__isset;
31834e58a64SDmitry Stogov	fcic.called_scope = ce;
3194182b085SDmitry Stogov	fcic.object = zobj;
32034e58a64SDmitry Stogov
32134e58a64SDmitry Stogov	zend_call_function(&fci, &fcic);
322345e0255SDmitry Stogov
323e9c3f9fcSDmitry Stogov	EG(fake_scope) = orig_fake_scope;
324345e0255SDmitry Stogov}
325b4892511SJani Taskinen/* }}} */
326471947b1SZeev Suraski
327bdeb220fSAnatol Belskistatic zend_always_inline int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce) /* {{{ */
328471947b1SZeev Suraski{
3296499162fSDmitry Stogov	zend_class_entry *scope;
3306499162fSDmitry Stogov
3316bcf121fSDmitry Stogov	if (property_info->flags & ZEND_ACC_PUBLIC) {
3326bcf121fSDmitry Stogov		return 1;
3336bcf121fSDmitry Stogov	} else if (property_info->flags & ZEND_ACC_PRIVATE) {
3346499162fSDmitry Stogov		if (EG(fake_scope)) {
3356499162fSDmitry Stogov			scope = EG(fake_scope);
3366499162fSDmitry Stogov		} else {
3376499162fSDmitry Stogov			scope = zend_get_executed_scope();
3386499162fSDmitry Stogov		}
3396499162fSDmitry Stogov		return (ce == scope || property_info->ce == scope);
3402d8d97ceSXinchen Hui	} else if (property_info->flags & ZEND_ACC_PROTECTED) {
3416499162fSDmitry Stogov		if (EG(fake_scope)) {
3426499162fSDmitry Stogov			scope = EG(fake_scope);
3436499162fSDmitry Stogov		} else {
3446499162fSDmitry Stogov			scope = zend_get_executed_scope();
3456499162fSDmitry Stogov		}
3466499162fSDmitry Stogov		return zend_check_protected(property_info->ce, scope);
347471947b1SZeev Suraski	}
3482d8d97ceSXinchen Hui	return 0;
349471947b1SZeev Suraski}
350b4892511SJani Taskinen/* }}} */
351471947b1SZeev Suraski
352c5237d82SDmitry Stogovstatic zend_always_inline zend_bool is_derived_class(zend_class_entry *child_class, zend_class_entry *parent_class) /* {{{ */
3537e72d8e8SZeev Suraski{
3547e72d8e8SZeev Suraski	child_class = child_class->parent;
3557e72d8e8SZeev Suraski	while (child_class) {
3567e72d8e8SZeev Suraski		if (child_class == parent_class) {
3577e72d8e8SZeev Suraski			return 1;
3587e72d8e8SZeev Suraski		}
3597e72d8e8SZeev Suraski		child_class = child_class->parent;
3607e72d8e8SZeev Suraski	}
3617e72d8e8SZeev Suraski
3627e72d8e8SZeev Suraski	return 0;
3637e72d8e8SZeev Suraski}
364b4892511SJani Taskinen/* }}} */
3657e72d8e8SZeev Suraski
3666a034be2SDmitry Stogovstatic zend_always_inline uintptr_t zend_get_property_offset(zend_class_entry *ce, zend_string *member, int silent, void **cache_slot) /* {{{ */
367fce275ebSZeev Suraski{
3688e1dc33dSDmitry Stogov	zval *zv;
3698e1dc33dSDmitry Stogov	zend_property_info *property_info = NULL;
3708e1dc33dSDmitry Stogov	uint32_t flags;
3716499162fSDmitry Stogov	zend_class_entry *scope;
37240326f6aSZeev Suraski
3732ed8a170SDmitry Stogov	if (cache_slot && EXPECTED(ce == CACHED_PTR_EX(cache_slot))) {
3746a034be2SDmitry Stogov		return (uintptr_t)CACHED_PTR_EX(cache_slot + 1);
375c5237d82SDmitry Stogov	}
376c5237d82SDmitry Stogov
3778e1dc33dSDmitry Stogov	if (UNEXPECTED(zend_hash_num_elements(&ce->properties_info) == 0)) {
3788e1dc33dSDmitry Stogov		goto exit_dynamic;
3798e1dc33dSDmitry Stogov	}
3808e1dc33dSDmitry Stogov
3818e1dc33dSDmitry Stogov	zv = zend_hash_find(&ce->properties_info, member);
3828e1dc33dSDmitry Stogov	if (EXPECTED(zv != NULL)) {
3838e1dc33dSDmitry Stogov		property_info = (zend_property_info*)Z_PTR_P(zv);
3848e1dc33dSDmitry Stogov		flags = property_info->flags;
3858e1dc33dSDmitry Stogov		if (UNEXPECTED((flags & ZEND_ACC_SHADOW) != 0)) {
3862cb52151SStanislav Malyshev			/* if it's a shadow - go to access it's private */
3872cb52151SStanislav Malyshev			property_info = NULL;
3882cb52151SStanislav Malyshev		} else {
389bdeb220fSAnatol Belski			if (EXPECTED(zend_verify_property_access(property_info, ce) != 0)) {
3908e1dc33dSDmitry Stogov				if (UNEXPECTED(!(flags & ZEND_ACC_CHANGED))
3918e1dc33dSDmitry Stogov					|| UNEXPECTED((flags & ZEND_ACC_PRIVATE))) {
39275041379SDmitry Stogov					if (UNEXPECTED((flags & ZEND_ACC_STATIC) != 0)) {
39375041379SDmitry Stogov						if (!silent) {
3947aa76271SDmitry Stogov							zend_error(E_NOTICE, "Accessing static property %s::$%s as non static", ZSTR_VAL(ce->name), ZSTR_VAL(member));
39575041379SDmitry Stogov						}
3965a24ac88SDmitry Stogov						return ZEND_DYNAMIC_PROPERTY_OFFSET;
3972cb52151SStanislav Malyshev					}
3988e1dc33dSDmitry Stogov					goto exit;
399d02d270fSDmitry Stogov				}
4002cb52151SStanislav Malyshev			} else {
4012cb52151SStanislav Malyshev				/* Try to look in the scope instead */
4028e1dc33dSDmitry Stogov				property_info = ZEND_WRONG_PROPERTY_INFO;
40340326f6aSZeev Suraski			}
404fce275ebSZeev Suraski		}
40588441904SZeev Suraski	}
406b7a7b1a6SStanislav Malyshev
4076499162fSDmitry Stogov	if (EG(fake_scope)) {
4086499162fSDmitry Stogov		scope = EG(fake_scope);
4096499162fSDmitry Stogov	} else {
4106499162fSDmitry Stogov		scope = zend_get_executed_scope();
4116499162fSDmitry Stogov	}
4126499162fSDmitry Stogov
4136499162fSDmitry Stogov	if (scope != ce
4146499162fSDmitry Stogov		&& scope
4156499162fSDmitry Stogov		&& is_derived_class(ce, scope)
4166499162fSDmitry Stogov		&& (zv = zend_hash_find(&scope->properties_info, member)) != NULL
4178e1dc33dSDmitry Stogov		&& ((zend_property_info*)Z_PTR_P(zv))->flags & ZEND_ACC_PRIVATE) {
4188e1dc33dSDmitry Stogov		property_info = (zend_property_info*)Z_PTR_P(zv);
4195a24ac88SDmitry Stogov		if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) != 0)) {
4205a24ac88SDmitry Stogov			return ZEND_DYNAMIC_PROPERTY_OFFSET;
42175041379SDmitry Stogov		}
4228e1dc33dSDmitry Stogov	} else if (UNEXPECTED(property_info == NULL)) {
4238e1dc33dSDmitry Stogovexit_dynamic:
424412dd75eSDmitry Stogov		if (UNEXPECTED(ZSTR_VAL(member)[0] == '\0' && ZSTR_LEN(member) != 0)) {
425412dd75eSDmitry Stogov			if (!silent) {
426412dd75eSDmitry Stogov				zend_throw_error(NULL, "Cannot access property started with '\\0'");
427412dd75eSDmitry Stogov			}
428412dd75eSDmitry Stogov			return ZEND_WRONG_PROPERTY_OFFSET;
429412dd75eSDmitry Stogov		}
4302ed8a170SDmitry Stogov		if (cache_slot) {
43159a7944bSDmitry Stogov			CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET);
432c5237d82SDmitry Stogov		}
4335a24ac88SDmitry Stogov		return ZEND_DYNAMIC_PROPERTY_OFFSET;
4348e1dc33dSDmitry Stogov	} else if (UNEXPECTED(property_info == ZEND_WRONG_PROPERTY_INFO)) {
4358e1dc33dSDmitry Stogov		/* Information was available, but we were denied access.  Error out. */
4368e1dc33dSDmitry Stogov		if (!silent) {
4375df893ceSAaron Piotrowski			zend_throw_error(NULL, "Cannot access %s property %s::$%s", zend_visibility_string(flags), ZSTR_VAL(ce->name), ZSTR_VAL(member));
43840326f6aSZeev Suraski		}
4395a24ac88SDmitry Stogov		return ZEND_WRONG_PROPERTY_OFFSET;
4408e1dc33dSDmitry Stogov	}
4418e1dc33dSDmitry Stogov
4428e1dc33dSDmitry Stogovexit:
4438e1dc33dSDmitry Stogov	if (cache_slot) {
4446a034be2SDmitry Stogov		CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, (void*)(uintptr_t)property_info->offset);
445fce275ebSZeev Suraski	}
4465a24ac88SDmitry Stogov	return property_info->offset;
447fce275ebSZeev Suraski}
448b4892511SJani Taskinen/* }}} */
449fce275ebSZeev Suraski
450bdeb220fSAnatol BelskiZEND_API zend_property_info *zend_get_property_info(zend_class_entry *ce, zend_string *member, int silent) /* {{{ */
45194dd8372SDmitry Stogov{
4525a24ac88SDmitry Stogov	zval *zv;
4535a24ac88SDmitry Stogov	zend_property_info *property_info = NULL;
4545a24ac88SDmitry Stogov	uint32_t flags;
4556499162fSDmitry Stogov	zend_class_entry *scope;
4565a24ac88SDmitry Stogov
4575a24ac88SDmitry Stogov	if (UNEXPECTED(zend_hash_num_elements(&ce->properties_info) == 0)) {
4585a24ac88SDmitry Stogov		goto exit_dynamic;
4595a24ac88SDmitry Stogov	}
4605a24ac88SDmitry Stogov
4615a24ac88SDmitry Stogov	zv = zend_hash_find(&ce->properties_info, member);
4625a24ac88SDmitry Stogov	if (EXPECTED(zv != NULL)) {
4635a24ac88SDmitry Stogov		property_info = (zend_property_info*)Z_PTR_P(zv);
4645a24ac88SDmitry Stogov		flags = property_info->flags;
4655a24ac88SDmitry Stogov		if (UNEXPECTED((flags & ZEND_ACC_SHADOW) != 0)) {
4665a24ac88SDmitry Stogov			/* if it's a shadow - go to access it's private */
4675a24ac88SDmitry Stogov			property_info = NULL;
4685a24ac88SDmitry Stogov		} else {
4695a24ac88SDmitry Stogov			if (EXPECTED(zend_verify_property_access(property_info, ce) != 0)) {
4705a24ac88SDmitry Stogov				if (UNEXPECTED(!(flags & ZEND_ACC_CHANGED))
4715a24ac88SDmitry Stogov					|| UNEXPECTED((flags & ZEND_ACC_PRIVATE))) {
4725a24ac88SDmitry Stogov					if (UNEXPECTED((flags & ZEND_ACC_STATIC) != 0)) {
4735a24ac88SDmitry Stogov						if (!silent) {
4747aa76271SDmitry Stogov							zend_error(E_NOTICE, "Accessing static property %s::$%s as non static", ZSTR_VAL(ce->name), ZSTR_VAL(member));
4755a24ac88SDmitry Stogov						}
4765a24ac88SDmitry Stogov					}
4775a24ac88SDmitry Stogov					goto exit;
4785a24ac88SDmitry Stogov				}
4795a24ac88SDmitry Stogov			} else {
4805a24ac88SDmitry Stogov				/* Try to look in the scope instead */
4815a24ac88SDmitry Stogov				property_info = ZEND_WRONG_PROPERTY_INFO;
4825a24ac88SDmitry Stogov			}
4835a24ac88SDmitry Stogov		}
4845a24ac88SDmitry Stogov	}
4855a24ac88SDmitry Stogov
4866499162fSDmitry Stogov	if (EG(fake_scope)) {
4876499162fSDmitry Stogov		scope = EG(fake_scope);
4886499162fSDmitry Stogov	} else {
4896499162fSDmitry Stogov		scope = zend_get_executed_scope();
4906499162fSDmitry Stogov	}
4916499162fSDmitry Stogov
4926499162fSDmitry Stogov	if (scope != ce
4936499162fSDmitry Stogov		&& scope
4946499162fSDmitry Stogov		&& is_derived_class(ce, scope)
4956499162fSDmitry Stogov		&& (zv = zend_hash_find(&scope->properties_info, member)) != NULL
4965a24ac88SDmitry Stogov		&& ((zend_property_info*)Z_PTR_P(zv))->flags & ZEND_ACC_PRIVATE) {
4975a24ac88SDmitry Stogov		property_info = (zend_property_info*)Z_PTR_P(zv);
4985a24ac88SDmitry Stogov	} else if (UNEXPECTED(property_info == NULL)) {
4995a24ac88SDmitry Stogovexit_dynamic:
500412dd75eSDmitry Stogov		if (UNEXPECTED(ZSTR_VAL(member)[0] == '\0' && ZSTR_LEN(member) != 0)) {
501412dd75eSDmitry Stogov			if (!silent) {
502412dd75eSDmitry Stogov				zend_throw_error(NULL, "Cannot access property started with '\\0'");
503412dd75eSDmitry Stogov			}
504412dd75eSDmitry Stogov			return ZEND_WRONG_PROPERTY_INFO;
505412dd75eSDmitry Stogov		}
5065a24ac88SDmitry Stogov		return NULL;
5075a24ac88SDmitry Stogov	} else if (UNEXPECTED(property_info == ZEND_WRONG_PROPERTY_INFO)) {
5085a24ac88SDmitry Stogov		/* Information was available, but we were denied access.  Error out. */
5095a24ac88SDmitry Stogov		if (!silent) {
5105df893ceSAaron Piotrowski			zend_throw_error(NULL, "Cannot access %s property %s::$%s", zend_visibility_string(flags), ZSTR_VAL(ce->name), ZSTR_VAL(member));
5115a24ac88SDmitry Stogov		}
5125a24ac88SDmitry Stogov		return ZEND_WRONG_PROPERTY_INFO;
5135a24ac88SDmitry Stogov	}
5145a24ac88SDmitry Stogov
5155a24ac88SDmitry Stogovexit:
5165a24ac88SDmitry Stogov	return property_info;
51794dd8372SDmitry Stogov}
51894dd8372SDmitry Stogov/* }}} */
51994dd8372SDmitry Stogov
520bdeb220fSAnatol BelskiZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_info_name) /* {{{ */
52149efcd4fSMarcus Boerger{
52249efcd4fSMarcus Boerger	zend_property_info *property_info;
5234456bfaaSDmitry Stogov	const char *class_name = NULL;
5244456bfaaSDmitry Stogov	const char *prop_name;
5254456bfaaSDmitry Stogov	zend_string *member;
526079409bbSNikita Popov	size_t prop_name_len;
52749efcd4fSMarcus Boerger
5287aa76271SDmitry Stogov	if (ZSTR_VAL(prop_info_name)[0] == 0) {
529079409bbSNikita Popov		zend_unmangle_property_name_ex(prop_info_name, &class_name, &prop_name, &prop_name_len);
530c3e3c98eSAnatol Belski		member = zend_string_init(prop_name, prop_name_len, 0);
5314456bfaaSDmitry Stogov	} else {
532c3e3c98eSAnatol Belski		member = zend_string_copy(prop_info_name);
5334456bfaaSDmitry Stogov	}
5345a24ac88SDmitry Stogov	property_info = zend_get_property_info(zobj->ce, member, 1);
5355eb1f92fSDmitry Stogov	zend_string_release_ex(member, 0);
5367471c217SDmitry Stogov	if (property_info == NULL) {
5377471c217SDmitry Stogov		/* undefined public property */
5387471c217SDmitry Stogov		if (class_name && class_name[0] != '*') {
5397471c217SDmitry Stogov			/* we we're looking for a private prop */
5407471c217SDmitry Stogov			return FAILURE;
5417471c217SDmitry Stogov		}
5427471c217SDmitry Stogov		return SUCCESS;
5437471c217SDmitry Stogov	} else if (property_info == ZEND_WRONG_PROPERTY_INFO) {
54449efcd4fSMarcus Boerger		return FAILURE;
54549efcd4fSMarcus Boerger	}
546b4892511SJani Taskinen	if (class_name && class_name[0] != '*') {
547cd88e646SDmitry Stogov		if (!(property_info->flags & ZEND_ACC_PRIVATE)) {
548cd88e646SDmitry Stogov			/* we we're looking for a private prop but found a non private one of the same name */
549cd88e646SDmitry Stogov			return FAILURE;
5507aa76271SDmitry Stogov		} else if (strcmp(ZSTR_VAL(prop_info_name)+1, ZSTR_VAL(property_info->name)+1)) {
551cd88e646SDmitry Stogov			/* we we're looking for a private prop but found a private one of the same name but another class */
552cd88e646SDmitry Stogov			return FAILURE;
553cd88e646SDmitry Stogov		}
55449efcd4fSMarcus Boerger	}
555bdeb220fSAnatol Belski	return zend_verify_property_access(property_info, zobj->ce) ? SUCCESS : FAILURE;
55649efcd4fSMarcus Boerger}
557b4892511SJani Taskinen/* }}} */
55849efcd4fSMarcus Boerger
5591a60175eSXinchen Huistatic void zend_property_guard_dtor(zval *el) /* {{{ */ {
560e88c71d3SDmitry Stogov	uint32_t *ptr = (uint32_t*)Z_PTR_P(el);
561e88c71d3SDmitry Stogov	if (EXPECTED(!(((zend_uintptr_t)ptr) & 1))) {
562e88c71d3SDmitry Stogov		efree_size(ptr, sizeof(uint32_t));
563e88c71d3SDmitry Stogov	}
5641a60175eSXinchen Hui}
5651a60175eSXinchen Hui/* }}} */
5661a60175eSXinchen Hui
5679ad40d8dSJoe WatkinsZEND_API uint32_t *zend_get_property_guard(zend_object *zobj, zend_string *member) /* {{{ */
56864931b62SDmitry Stogov{
5699e70d767SDmitry Stogov	HashTable *guards;
570e88c71d3SDmitry Stogov	zval *zv;
571e88c71d3SDmitry Stogov	uint32_t *ptr;
5729e70d767SDmitry Stogov
57358880e3fSDmitry Stogov	ZEND_ASSERT(zobj->ce->ce_flags & ZEND_ACC_USE_GUARDS);
574e88c71d3SDmitry Stogov	zv = zobj->properties_table + zobj->ce->default_properties_count;
575e88c71d3SDmitry Stogov	if (EXPECTED(Z_TYPE_P(zv) == IS_STRING)) {
576e88c71d3SDmitry Stogov		zend_string *str = Z_STR_P(zv);
577e88c71d3SDmitry Stogov		if (EXPECTED(str == member) ||
578e88c71d3SDmitry Stogov		     /* hash values are always pred-calculated here */
579e88c71d3SDmitry Stogov		    (EXPECTED(ZSTR_H(str) == ZSTR_H(member)) &&
58074c84cd7SDmitry Stogov		     EXPECTED(zend_string_equal_content(str, member)))) {
5815e8aa036SDmitry Stogov			return &Z_PROPERTY_GUARD_P(zv);
5825e8aa036SDmitry Stogov		} else if (EXPECTED(Z_PROPERTY_GUARD_P(zv) == 0)) {
583af341213SDmitry Stogov			zval_ptr_dtor_str(zv);
584e88c71d3SDmitry Stogov			ZVAL_STR_COPY(zv, member);
5855e8aa036SDmitry Stogov			return &Z_PROPERTY_GUARD_P(zv);
586e88c71d3SDmitry Stogov		} else {
587e88c71d3SDmitry Stogov			ALLOC_HASHTABLE(guards);
588e88c71d3SDmitry Stogov			zend_hash_init(guards, 8, NULL, zend_property_guard_dtor, 0);
589e88c71d3SDmitry Stogov			/* mark pointer as "special" using low bit */
590fe46a7daSNikita Popov			zend_hash_add_new_ptr(guards, str,
5915e8aa036SDmitry Stogov				(void*)(((zend_uintptr_t)&Z_PROPERTY_GUARD_P(zv)) | 1));
592af341213SDmitry Stogov			zval_ptr_dtor_str(zv);
593e88c71d3SDmitry Stogov			ZVAL_ARR(zv, guards);
594e88c71d3SDmitry Stogov		}
595e88c71d3SDmitry Stogov	} else if (EXPECTED(Z_TYPE_P(zv) == IS_ARRAY)) {
596e88c71d3SDmitry Stogov		guards = Z_ARRVAL_P(zv);
5979e70d767SDmitry Stogov		ZEND_ASSERT(guards != NULL);
598e88c71d3SDmitry Stogov		zv = zend_hash_find(guards, member);
599e88c71d3SDmitry Stogov		if (zv != NULL) {
600e88c71d3SDmitry Stogov			return (uint32_t*)(((zend_uintptr_t)Z_PTR_P(zv)) & ~1);
6019e70d767SDmitry Stogov		}
6029e70d767SDmitry Stogov	} else {
603e88c71d3SDmitry Stogov		ZEND_ASSERT(Z_TYPE_P(zv) == IS_UNDEF);
604e88c71d3SDmitry Stogov		ZVAL_STR_COPY(zv, member);
6055e8aa036SDmitry Stogov		Z_PROPERTY_GUARD_P(zv) = 0;
6065e8aa036SDmitry Stogov		return &Z_PROPERTY_GUARD_P(zv);
607e88c71d3SDmitry Stogov	}
608e88c71d3SDmitry Stogov	/* we have to allocate uint32_t separately because ht->arData may be reallocated */
609e88c71d3SDmitry Stogov	ptr = (uint32_t*)emalloc(sizeof(uint32_t));
610e88c71d3SDmitry Stogov	*ptr = 0;
611e88c71d3SDmitry Stogov	return (uint32_t*)zend_hash_add_new_ptr(guards, member, ptr);
61264931b62SDmitry Stogov}
613b4892511SJani Taskinen/* }}} */
61464931b62SDmitry Stogov
615f2b4ec4bSDmitry StogovZEND_API zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv) /* {{{ */
6166608f073SStanislav Malyshev{
6176608f073SStanislav Malyshev	zend_object *zobj;
61857527455SDmitry Stogov	zend_string *name, *tmp_name;
619f4cfaf36SDmitry Stogov	zval *retval;
6206a034be2SDmitry Stogov	uintptr_t property_offset;
6213c4c9a23SXinchen Hui	uint32_t *guard = NULL;
622bd9b600cSStanislav Malyshev
6236ac6cb10SHarald Radi	zobj = Z_OBJ_P(object);
62457527455SDmitry Stogov	name = zval_get_tmp_string(member, &tmp_name);
6256608f073SStanislav Malyshev
6266608f073SStanislav Malyshev#if DEBUG_OBJECT_HANDLERS
62757527455SDmitry Stogov	fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), ZSTR_VAL(name));
6288ce1211aSMarcus Boerger#endif
629471947b1SZeev Suraski
630e000da96SStanislav Malyshev	/* make zend_get_property_info silent if we have getter - we may want to use it */
63157527455SDmitry Stogov	property_offset = zend_get_property_offset(zobj->ce, name, (type == BP_VAR_IS) || (zobj->ce->__get != NULL), cache_slot);
632471947b1SZeev Suraski
6330fb05f14SDmitry Stogov	if (EXPECTED(IS_VALID_PROPERTY_OFFSET(property_offset))) {
6340fb05f14SDmitry Stogov		retval = OBJ_PROP(zobj, property_offset);
6350fb05f14SDmitry Stogov		if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
6360fb05f14SDmitry Stogov			goto exit;
6370fb05f14SDmitry Stogov		}
6380fb05f14SDmitry Stogov	} else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(property_offset))) {
6390fb05f14SDmitry Stogov		if (EXPECTED(zobj->properties != NULL)) {
640193adbdfSDmitry Stogov			if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(property_offset)) {
6416a034be2SDmitry Stogov				uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(property_offset);
642193adbdfSDmitry Stogov
64359a7944bSDmitry Stogov				if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) {
64459a7944bSDmitry Stogov					Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx);
645193adbdfSDmitry Stogov
646193adbdfSDmitry Stogov					if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) &&
64757527455SDmitry Stogov				        (EXPECTED(p->key == name) ||
64857527455SDmitry Stogov				         (EXPECTED(p->h == ZSTR_H(name)) &&
649193adbdfSDmitry Stogov				          EXPECTED(p->key != NULL) &&
65057527455SDmitry Stogov				          EXPECTED(zend_string_equal_content(p->key, name))))) {
651193adbdfSDmitry Stogov						retval = &p->val;
652193adbdfSDmitry Stogov						goto exit;
653193adbdfSDmitry Stogov					}
654193adbdfSDmitry Stogov				}
65559a7944bSDmitry Stogov				CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET);
656193adbdfSDmitry Stogov			}
65757527455SDmitry Stogov			retval = zend_hash_find(zobj->properties, name);
658193adbdfSDmitry Stogov			if (EXPECTED(retval)) {
659193adbdfSDmitry Stogov				if (cache_slot) {
6606a034be2SDmitry Stogov					uintptr_t idx = (char*)retval - (char*)zobj->properties->arData;
66159a7944bSDmitry Stogov					CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx));
662193adbdfSDmitry Stogov				}
663193adbdfSDmitry Stogov				goto exit;
664193adbdfSDmitry Stogov			}
665f4cfaf36SDmitry Stogov		}
6662bf8f29dSDmitry Stogov	} else if (UNEXPECTED(EG(exception))) {
6672bf8f29dSDmitry Stogov		retval = &EG(uninitialized_zval);
6682bf8f29dSDmitry Stogov		goto exit;
669f4cfaf36SDmitry Stogov	}
670f4cfaf36SDmitry Stogov
6716f289564SJoe Watkins	/* magic isset */
6726f289564SJoe Watkins	if ((type == BP_VAR_IS) && zobj->ce->__isset) {
673917dfe64SDmitry Stogov		zval tmp_result;
67457527455SDmitry Stogov		guard = zend_get_property_guard(zobj, name);
6756f289564SJoe Watkins
6766f289564SJoe Watkins		if (!((*guard) & IN_ISSET)) {
67757527455SDmitry Stogov			if (!tmp_name && !ZSTR_IS_INTERNED(name)) {
67857527455SDmitry Stogov				tmp_name = zend_string_copy(name);
679bc59289bSDmitry Stogov			}
6804182b085SDmitry Stogov			GC_ADDREF(zobj);
6816f289564SJoe Watkins			ZVAL_UNDEF(&tmp_result);
6826f289564SJoe Watkins
6836f289564SJoe Watkins			*guard |= IN_ISSET;
68457527455SDmitry Stogov			zend_std_call_issetter(zobj, name, &tmp_result);
6856f289564SJoe Watkins			*guard &= ~IN_ISSET;
68664002648SGabriel Caruso
6876f289564SJoe Watkins			if (!zend_is_true(&tmp_result)) {
6886f289564SJoe Watkins				retval = &EG(uninitialized_zval);
6894182b085SDmitry Stogov				OBJ_RELEASE(zobj);
6906f289564SJoe Watkins				zval_ptr_dtor(&tmp_result);
6916f289564SJoe Watkins				goto exit;
6926f289564SJoe Watkins			}
6936f289564SJoe Watkins
6946f289564SJoe Watkins			zval_ptr_dtor(&tmp_result);
6954182b085SDmitry Stogov			if (zobj->ce->__get && !((*guard) & IN_GET)) {
6964182b085SDmitry Stogov				goto call_getter;
6974182b085SDmitry Stogov			}
6984182b085SDmitry Stogov			OBJ_RELEASE(zobj);
6994182b085SDmitry Stogov		} else if (zobj->ce->__get && !((*guard) & IN_GET)) {
7004182b085SDmitry Stogov			goto call_getter_addref;
7016f289564SJoe Watkins		}
7024182b085SDmitry Stogov	} else if (zobj->ce->__get) {
7034182b085SDmitry Stogov		/* magic get */
70457527455SDmitry Stogov		guard = zend_get_property_guard(zobj, name);
705f4cfaf36SDmitry Stogov		if (!((*guard) & IN_GET)) {
706d8651c82SStanislav Malyshev			/* have getter - try with it! */
7074182b085SDmitry Stogovcall_getter_addref:
7084182b085SDmitry Stogov			GC_ADDREF(zobj);
7094182b085SDmitry Stogovcall_getter:
710f4cfaf36SDmitry Stogov			*guard |= IN_GET; /* prevent circular getting */
71157527455SDmitry Stogov			zend_std_call_getter(zobj, name, rv);
712f4cfaf36SDmitry Stogov			*guard &= ~IN_GET;
713d8651c82SStanislav Malyshev
7141c3ba95bSDmitry Stogov			if (Z_TYPE_P(rv) != IS_UNDEF) {
7151c3ba95bSDmitry Stogov				retval = rv;
7164b4d634cSYiduo (David) Wang				if (!Z_ISREF_P(rv) &&
717e470e22eSDmitry Stogov				    (type == BP_VAR_W || type == BP_VAR_RW  || type == BP_VAR_UNSET)) {
718277f271aSDmitry Stogov					if (UNEXPECTED(Z_TYPE_P(rv) != IS_OBJECT)) {
71957527455SDmitry Stogov						zend_error(E_NOTICE, "Indirect modification of overloaded property %s::$%s has no effect", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name));
72033a1a4d3SDmitry Stogov					}
72133a1a4d3SDmitry Stogov				}
722d8651c82SStanislav Malyshev			} else {
7231c3ba95bSDmitry Stogov				retval = &EG(uninitialized_zval);
724d8651c82SStanislav Malyshev			}
7254182b085SDmitry Stogov			OBJ_RELEASE(zobj);
7267471c217SDmitry Stogov			goto exit;
72757527455SDmitry Stogov		} else if (ZSTR_VAL(name)[0] == '\0' && ZSTR_LEN(name) != 0) {
7283b9ba7b6SXinchen Hui			zend_throw_error(NULL, "Cannot access property started with '\\0'");
7293b9ba7b6SXinchen Hui			retval = &EG(uninitialized_zval);
7303b9ba7b6SXinchen Hui			goto exit;
731f4cfaf36SDmitry Stogov		}
7326608f073SStanislav Malyshev	}
733bc59289bSDmitry Stogov
7347471c217SDmitry Stogov	if ((type != BP_VAR_IS)) {
73557527455SDmitry Stogov		zend_error(E_NOTICE,"Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name));
7367471c217SDmitry Stogov	}
7377471c217SDmitry Stogov	retval = &EG(uninitialized_zval);
738887189caSDmitry Stogov
739f4cfaf36SDmitry Stogovexit:
74057527455SDmitry Stogov	zend_tmp_string_release(tmp_name);
7416852f9cdSXinchen Hui
742f4cfaf36SDmitry Stogov	return retval;
7436608f073SStanislav Malyshev}
744b4892511SJani Taskinen/* }}} */
7456608f073SStanislav Malyshev
746bdeb220fSAnatol BelskiZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */
7476608f073SStanislav Malyshev{
7486608f073SStanislav Malyshev	zend_object *zobj;
74957527455SDmitry Stogov	zend_string *name, *tmp_name;
750f4cfaf36SDmitry Stogov	zval *variable_ptr;
7516a034be2SDmitry Stogov	uintptr_t property_offset;
752e000da96SStanislav Malyshev
7536ac6cb10SHarald Radi	zobj = Z_OBJ_P(object);
75457527455SDmitry Stogov	name = zval_get_tmp_string(member, &tmp_name);
7556608f073SStanislav Malyshev
75657527455SDmitry Stogov	property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__set != NULL), cache_slot);
757471947b1SZeev Suraski
7580fb05f14SDmitry Stogov	if (EXPECTED(IS_VALID_PROPERTY_OFFSET(property_offset))) {
7590fb05f14SDmitry Stogov		variable_ptr = OBJ_PROP(zobj, property_offset);
7600fb05f14SDmitry Stogov		if (Z_TYPE_P(variable_ptr) != IS_UNDEF) {
7610fb05f14SDmitry Stogov			goto found;
7620fb05f14SDmitry Stogov		}
7630fb05f14SDmitry Stogov	} else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(property_offset))) {
7640fb05f14SDmitry Stogov		if (EXPECTED(zobj->properties != NULL)) {
7654a6e1345SDmitry Stogov			if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
7664a6e1345SDmitry Stogov				if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
76749ea143bSDmitry Stogov					GC_DELREF(zobj->properties);
7684a6e1345SDmitry Stogov				}
7694a6e1345SDmitry Stogov				zobj->properties = zend_array_dup(zobj->properties);
7704a6e1345SDmitry Stogov			}
77157527455SDmitry Stogov			if ((variable_ptr = zend_hash_find(zobj->properties, name)) != NULL) {
772f4cfaf36SDmitry Stogovfound:
773adcf0c60SDmitry Stogov				zend_assign_to_variable(variable_ptr, value, IS_CV);
774887189caSDmitry Stogov				goto exit;
7756608f073SStanislav Malyshev			}
7766608f073SStanislav Malyshev		}
7772bf8f29dSDmitry Stogov	} else if (UNEXPECTED(EG(exception))) {
7782bf8f29dSDmitry Stogov		goto exit;
779f4cfaf36SDmitry Stogov	}
780f4cfaf36SDmitry Stogov
781887189caSDmitry Stogov	/* magic set */
782f4cfaf36SDmitry Stogov	if (zobj->ce->__set) {
78357527455SDmitry Stogov		uint32_t *guard = zend_get_property_guard(zobj, name);
78464931b62SDmitry Stogov
785f4cfaf36SDmitry Stogov	    if (!((*guard) & IN_SET)) {
7864182b085SDmitry Stogov			GC_ADDREF(zobj);
787f4cfaf36SDmitry Stogov			(*guard) |= IN_SET; /* prevent circular setting */
78857527455SDmitry Stogov			zend_std_call_setter(zobj, name, value);
789f4cfaf36SDmitry Stogov			(*guard) &= ~IN_SET;
7904182b085SDmitry Stogov			OBJ_RELEASE(zobj);
7910fb05f14SDmitry Stogov		} else if (EXPECTED(!IS_WRONG_PROPERTY_OFFSET(property_offset))) {
7925343cd32SDmitry Stogov			goto write_std_property;
793f4cfaf36SDmitry Stogov		} else {
79457527455SDmitry Stogov			if (ZSTR_VAL(name)[0] == '\0' && ZSTR_LEN(name) != 0) {
795674297c7SNikita Popov				zend_throw_error(NULL, "Cannot access property started with '\\0'");
796674297c7SNikita Popov				goto exit;
797f64e4bacSDmitry Stogov			}
798e22e61a4SStanislav Malyshev		}
7990fb05f14SDmitry Stogov	} else if (EXPECTED(!IS_WRONG_PROPERTY_OFFSET(property_offset))) {
8005343cd32SDmitry Stogovwrite_std_property:
80137337373SDmitry Stogov		if (Z_REFCOUNTED_P(value)) {
8029067dbcdSDmitry Stogov			if (Z_ISREF_P(value)) {
803eda5ba1fSNikita Popov				/* if we assign referenced variable, we should separate it */
8040db8c974SDmitry Stogov				value = Z_REFVAL_P(value);
8050db8c974SDmitry Stogov				if (Z_REFCOUNTED_P(value)) {
8060db8c974SDmitry Stogov					Z_ADDREF_P(value);
8070db8c974SDmitry Stogov				}
808db7b5325SDmitry Stogov			} else {
809db7b5325SDmitry Stogov				Z_ADDREF_P(value);
8109067dbcdSDmitry Stogov			}
811f4cfaf36SDmitry Stogov		}
8120fb05f14SDmitry Stogov		if (EXPECTED(IS_VALID_PROPERTY_OFFSET(property_offset))) {
8135a24ac88SDmitry Stogov			ZVAL_COPY_VALUE(OBJ_PROP(zobj, property_offset), value);
814f4cfaf36SDmitry Stogov		} else {
815f4cfaf36SDmitry Stogov			if (!zobj->properties) {
816f4cfaf36SDmitry Stogov				rebuild_object_properties(zobj);
817f4cfaf36SDmitry Stogov			}
81857527455SDmitry Stogov			zend_hash_add_new(zobj->properties, name, value);
819f4cfaf36SDmitry Stogov		}
820d8651c82SStanislav Malyshev	}
82130f4d3f9SDmitry Stogov
822887189caSDmitry Stogovexit:
82357527455SDmitry Stogov	zend_tmp_string_release(tmp_name);
8246608f073SStanislav Malyshev}
825b4892511SJani Taskinen/* }}} */
8266608f073SStanislav Malyshev
827f2b4ec4bSDmitry StogovZEND_API zval *zend_std_read_dimension(zval *object, zval *offset, int type, zval *rv) /* {{{ */
8283cfa6a68SZeev Suraski{
8294dba05d9SMarcus Boerger	zend_class_entry *ce = Z_OBJCE_P(object);
83098eee907SDmitry Stogov	zval tmp_offset, tmp_object;
831637a4042SMarcus Boerger
832bdeb220fSAnatol Belski	if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) {
833a175aa9dSNikita Popov		if (offset == NULL) {
83428d72ce2SStanislav Malyshev			/* [] construct */
83598eee907SDmitry Stogov			ZVAL_NULL(&tmp_offset);
836fd4fe1c8SDmitry Stogov		} else {
83767b4c337SDmitry Stogov			ZVAL_COPY_DEREF(&tmp_offset, offset);
83828d72ce2SStanislav Malyshev		}
839a175aa9dSNikita Popov
84098eee907SDmitry Stogov		ZVAL_COPY(&tmp_object, object);
841a175aa9dSNikita Popov		if (type == BP_VAR_IS) {
84298eee907SDmitry Stogov			zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetexists", rv, &tmp_offset);
843a175aa9dSNikita Popov			if (UNEXPECTED(Z_ISUNDEF_P(rv))) {
84498eee907SDmitry Stogov				zval_ptr_dtor(&tmp_object);
84598eee907SDmitry Stogov				zval_ptr_dtor(&tmp_offset);
846a175aa9dSNikita Popov				return NULL;
847a175aa9dSNikita Popov			}
848a175aa9dSNikita Popov			if (!i_zend_is_true(rv)) {
84998eee907SDmitry Stogov				zval_ptr_dtor(&tmp_object);
85098eee907SDmitry Stogov				zval_ptr_dtor(&tmp_offset);
851a175aa9dSNikita Popov				zval_ptr_dtor(rv);
852a175aa9dSNikita Popov				return &EG(uninitialized_zval);
853a175aa9dSNikita Popov			}
854a175aa9dSNikita Popov			zval_ptr_dtor(rv);
855a175aa9dSNikita Popov		}
856a175aa9dSNikita Popov
85798eee907SDmitry Stogov		zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetget", rv, &tmp_offset);
858d673ec01SStanislav Malyshev
85998eee907SDmitry Stogov		zval_ptr_dtor(&tmp_object);
86098eee907SDmitry Stogov		zval_ptr_dtor(&tmp_offset);
861d673ec01SStanislav Malyshev
8621c3ba95bSDmitry Stogov		if (UNEXPECTED(Z_TYPE_P(rv) == IS_UNDEF)) {
863277f271aSDmitry Stogov			if (UNEXPECTED(!EG(exception))) {
8645df893ceSAaron Piotrowski				zend_throw_error(NULL, "Undefined offset for object of type %s used as array", ZSTR_VAL(ce->name));
865904373a8SMarcus Boerger			}
866f4cfaf36SDmitry Stogov			return NULL;
867904373a8SMarcus Boerger		}
8681c3ba95bSDmitry Stogov		return rv;
8694dba05d9SMarcus Boerger	} else {
8705df893ceSAaron Piotrowski		zend_throw_error(NULL, "Cannot use object of type %s as array", ZSTR_VAL(ce->name));
871f4cfaf36SDmitry Stogov		return NULL;
8724dba05d9SMarcus Boerger	}
8733cfa6a68SZeev Suraski}
874b4892511SJani Taskinen/* }}} */
8753cfa6a68SZeev Suraski
876f2b4ec4bSDmitry StogovZEND_API void zend_std_write_dimension(zval *object, zval *offset, zval *value) /* {{{ */
877938c0fbcSZeev Suraski{
8784dba05d9SMarcus Boerger	zend_class_entry *ce = Z_OBJCE_P(object);
87998eee907SDmitry Stogov	zval tmp_offset, tmp_object;
880fd4fe1c8SDmitry Stogov
881bdeb220fSAnatol Belski	if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) {
88206788f04SMarcus Boerger		if (!offset) {
88398eee907SDmitry Stogov			ZVAL_NULL(&tmp_offset);
884fd4fe1c8SDmitry Stogov		} else {
88567b4c337SDmitry Stogov			ZVAL_COPY_DEREF(&tmp_offset, offset);
88606788f04SMarcus Boerger		}
88798eee907SDmitry Stogov		ZVAL_COPY(&tmp_object, object);
88898eee907SDmitry Stogov		zend_call_method_with_2_params(&tmp_object, ce, NULL, "offsetset", NULL, &tmp_offset, value);
88998eee907SDmitry Stogov		zval_ptr_dtor(&tmp_object);
89098eee907SDmitry Stogov		zval_ptr_dtor(&tmp_offset);
8914dba05d9SMarcus Boerger	} else {
8925df893ceSAaron Piotrowski		zend_throw_error(NULL, "Cannot use object of type %s as array", ZSTR_VAL(ce->name));
8934dba05d9SMarcus Boerger	}
894938c0fbcSZeev Suraski}
895b4892511SJani Taskinen/* }}} */
896938c0fbcSZeev Suraski
897f2b4ec4bSDmitry StogovZEND_API int zend_std_has_dimension(zval *object, zval *offset, int check_empty) /* {{{ */
898296529b8SMarcus Boerger{
8994dba05d9SMarcus Boerger	zend_class_entry *ce = Z_OBJCE_P(object);
90098eee907SDmitry Stogov	zval retval, tmp_offset, tmp_object;
9014dba05d9SMarcus Boerger	int result;
902637a4042SMarcus Boerger
903bdeb220fSAnatol Belski	if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) {
9047da042cbSDmitry Stogov		ZVAL_COPY_DEREF(&tmp_offset, offset);
90598eee907SDmitry Stogov		ZVAL_COPY(&tmp_object, object);
90698eee907SDmitry Stogov		zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetexists", &retval, &tmp_offset);
907c42f0ba4SDmitry Stogov		result = i_zend_is_true(&retval);
908c42f0ba4SDmitry Stogov		zval_ptr_dtor(&retval);
909c42f0ba4SDmitry Stogov		if (check_empty && result && EXPECTED(!EG(exception))) {
910c42f0ba4SDmitry Stogov			zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetget", &retval, &tmp_offset);
911bdeb220fSAnatol Belski			result = i_zend_is_true(&retval);
9126a6eaf2bSMarcus Boerger			zval_ptr_dtor(&retval);
9136a6eaf2bSMarcus Boerger		}
91498eee907SDmitry Stogov		zval_ptr_dtor(&tmp_object);
91598eee907SDmitry Stogov		zval_ptr_dtor(&tmp_offset);
9164dba05d9SMarcus Boerger	} else {
9175df893ceSAaron Piotrowski		zend_throw_error(NULL, "Cannot use object of type %s as array", ZSTR_VAL(ce->name));
9184dba05d9SMarcus Boerger		return 0;
9194dba05d9SMarcus Boerger	}
920345e0255SDmitry Stogov	return result;
921296529b8SMarcus Boerger}
922b4892511SJani Taskinen/* }}} */
923296529b8SMarcus Boerger
924f2b4ec4bSDmitry StogovZEND_API zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot) /* {{{ */
9256608f073SStanislav Malyshev{
9266608f073SStanislav Malyshev	zend_object *zobj;
927ccc12b82SDmitry Stogov	zend_string *name, *tmp_name;
9287471c217SDmitry Stogov	zval *retval = NULL;
9296a034be2SDmitry Stogov	uintptr_t property_offset;
930637a4042SMarcus Boerger
9316ac6cb10SHarald Radi	zobj = Z_OBJ_P(object);
932ccc12b82SDmitry Stogov	name = zval_get_tmp_string(member, &tmp_name);
9336608f073SStanislav Malyshev
9346608f073SStanislav Malyshev#if DEBUG_OBJECT_HANDLERS
9357aa76271SDmitry Stogov	fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), ZSTR_VAL(name));
936637a4042SMarcus Boerger#endif
9376608f073SStanislav Malyshev
9385a24ac88SDmitry Stogov	property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__get != NULL), cache_slot);
939da12870cSZeev Suraski
9400fb05f14SDmitry Stogov	if (EXPECTED(IS_VALID_PROPERTY_OFFSET(property_offset))) {
9410fb05f14SDmitry Stogov		retval = OBJ_PROP(zobj, property_offset);
9420fb05f14SDmitry Stogov		if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) {
9434a6e1345SDmitry Stogov			if (EXPECTED(!zobj->ce->__get) ||
9444a6e1345SDmitry Stogov			    UNEXPECTED((*zend_get_property_guard(zobj, name)) & IN_GET)) {
9450fb05f14SDmitry Stogov				ZVAL_NULL(retval);
9464a6e1345SDmitry Stogov				/* Notice is thrown after creation of the property, to avoid EG(std_property_info)
9474a6e1345SDmitry Stogov				 * being overwritten in an error handler. */
9484a6e1345SDmitry Stogov				if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
9497aa76271SDmitry Stogov					zend_error(E_NOTICE, "Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name));
9504a6e1345SDmitry Stogov				}
9510fb05f14SDmitry Stogov			} else {
9520fb05f14SDmitry Stogov				/* we do have getter - fail and let it try again with usual get/set */
9530fb05f14SDmitry Stogov				retval = NULL;
9540fb05f14SDmitry Stogov			}
9550fb05f14SDmitry Stogov		}
9560fb05f14SDmitry Stogov	} else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(property_offset))) {
9570fb05f14SDmitry Stogov		if (EXPECTED(zobj->properties)) {
9580fb05f14SDmitry Stogov			if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
9590fb05f14SDmitry Stogov				if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
96049ea143bSDmitry Stogov					GC_DELREF(zobj->properties);
9610fb05f14SDmitry Stogov				}
9620fb05f14SDmitry Stogov				zobj->properties = zend_array_dup(zobj->properties);
9630fb05f14SDmitry Stogov			}
9640fb05f14SDmitry Stogov		    if (EXPECTED((retval = zend_hash_find(zobj->properties, name)) != NULL)) {
965ccc12b82SDmitry Stogov				zend_tmp_string_release(tmp_name);
9660fb05f14SDmitry Stogov				return retval;
9670fb05f14SDmitry Stogov		    }
9680fb05f14SDmitry Stogov		}
9690fb05f14SDmitry Stogov		if (EXPECTED(!zobj->ce->__get) ||
9700fb05f14SDmitry Stogov		    UNEXPECTED((*zend_get_property_guard(zobj, name)) & IN_GET)) {
9710fb05f14SDmitry Stogov			if (UNEXPECTED(!zobj->properties)) {
9720fb05f14SDmitry Stogov				rebuild_object_properties(zobj);
9730fb05f14SDmitry Stogov			}
9740fb05f14SDmitry Stogov			retval = zend_hash_update(zobj->properties, name, &EG(uninitialized_zval));
9750fb05f14SDmitry Stogov			/* Notice is thrown after creation of the property, to avoid EG(std_property_info)
9760fb05f14SDmitry Stogov			 * being overwritten in an error handler. */
9770fb05f14SDmitry Stogov			if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
9780fb05f14SDmitry Stogov				zend_error(E_NOTICE, "Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name));
979f4cfaf36SDmitry Stogov			}
980d8651c82SStanislav Malyshev		}
9816608f073SStanislav Malyshev	}
982f4cfaf36SDmitry Stogov
983ccc12b82SDmitry Stogov	zend_tmp_string_release(tmp_name);
9846608f073SStanislav Malyshev	return retval;
9856608f073SStanislav Malyshev}
986b4892511SJani Taskinen/* }}} */
9876608f073SStanislav Malyshev
988f2b4ec4bSDmitry StogovZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_slot) /* {{{ */
9896608f073SStanislav Malyshev{
9906608f073SStanislav Malyshev	zend_object *zobj;
99157527455SDmitry Stogov	zend_string *name, *tmp_name;
9926a034be2SDmitry Stogov	uintptr_t property_offset;
993637a4042SMarcus Boerger
9946ac6cb10SHarald Radi	zobj = Z_OBJ_P(object);
99557527455SDmitry Stogov	name = zval_get_tmp_string(member, &tmp_name);
9966608f073SStanislav Malyshev
99757527455SDmitry Stogov	property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__unset != NULL), cache_slot);
998637a4042SMarcus Boerger
9990fb05f14SDmitry Stogov	if (EXPECTED(IS_VALID_PROPERTY_OFFSET(property_offset))) {
10000fb05f14SDmitry Stogov		zval *slot = OBJ_PROP(zobj, property_offset);
10017471c217SDmitry Stogov
10020fb05f14SDmitry Stogov		if (Z_TYPE_P(slot) != IS_UNDEF) {
10030fb05f14SDmitry Stogov			zval_ptr_dtor(slot);
10040fb05f14SDmitry Stogov			ZVAL_UNDEF(slot);
10050fb05f14SDmitry Stogov			if (zobj->properties) {
10066634d5e3SDmitry Stogov				HT_FLAGS(zobj->properties) |= HASH_FLAG_HAS_EMPTY_IND;
10074a6e1345SDmitry Stogov			}
10080fb05f14SDmitry Stogov			goto exit;
10090fb05f14SDmitry Stogov		}
10100fb05f14SDmitry Stogov	} else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(property_offset))
10110fb05f14SDmitry Stogov	 && EXPECTED(zobj->properties != NULL)) {
10120fb05f14SDmitry Stogov		if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
10130fb05f14SDmitry Stogov			if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
101449ea143bSDmitry Stogov				GC_DELREF(zobj->properties);
10154a6e1345SDmitry Stogov			}
10160fb05f14SDmitry Stogov			zobj->properties = zend_array_dup(zobj->properties);
10170fb05f14SDmitry Stogov		}
101857527455SDmitry Stogov		if (EXPECTED(zend_hash_del(zobj->properties, name) != FAILURE)) {
10190fb05f14SDmitry Stogov			goto exit;
1020887189caSDmitry Stogov		}
10212bf8f29dSDmitry Stogov	} else if (UNEXPECTED(EG(exception))) {
10222bf8f29dSDmitry Stogov		goto exit;
1023f4cfaf36SDmitry Stogov	}
1024b7a7b1a6SStanislav Malyshev
1025887189caSDmitry Stogov	/* magic unset */
1026887189caSDmitry Stogov	if (zobj->ce->__unset) {
102757527455SDmitry Stogov		uint32_t *guard = zend_get_property_guard(zobj, name);
1028887189caSDmitry Stogov		if (!((*guard) & IN_UNSET)) {
1029887189caSDmitry Stogov			/* have unseter - try with it! */
1030887189caSDmitry Stogov			(*guard) |= IN_UNSET; /* prevent circular unsetting */
103157527455SDmitry Stogov			zend_std_call_unsetter(zobj, name);
1032887189caSDmitry Stogov			(*guard) &= ~IN_UNSET;
1033887189caSDmitry Stogov		} else {
103457527455SDmitry Stogov			if (ZSTR_VAL(name)[0] == '\0' && ZSTR_LEN(name) != 0) {