summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend.h7
-rw-r--r--Zend/zend_compile.c16
-rw-r--r--Zend/zend_compile.h7
-rw-r--r--Zend/zend_execute.c55
-rw-r--r--Zend/zend_extensions.h2
-rw-r--r--Zend/zend_object_handlers.c289
-rw-r--r--Zend/zend_objects.c2
7 files changed, 335 insertions, 43 deletions
diff --git a/Zend/zend.h b/Zend/zend.h
index d9de24d4f0..2b28eedc4f 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -226,6 +226,8 @@ typedef struct _zend_class_entry zend_class_entry;
typedef struct _zend_object {
zend_class_entry *ce;
HashTable *properties;
+ int in_get:1;
+ int in_set:1;
} zend_object;
typedef unsigned int zend_object_handle;
@@ -311,9 +313,14 @@ struct _zend_class_entry {
union _zend_function *constructor;
union _zend_function *destructor;
union _zend_function *clone;
+ union _zend_function *__get;
+ union _zend_function *__set;
+ union _zend_function *__call;
/* handlers */
zend_object_value (*create_object)(zend_class_entry *class_type TSRMLS_DC);
+
+ /* old handlers */
void (*handle_function_call)(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
zval (*handle_property_get)(zend_property_reference *property_reference);
int (*handle_property_set)(zend_property_reference *property_reference, zval *value);
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index bb7403b0c2..4cf790a87c 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -895,10 +895,6 @@ void zend_do_free(znode *op1 TSRMLS_DC)
}
}
-#define ZEND_CLONE_FUNC_NAME "__clone"
-#define ZEND_CONSTRUCTOR_FUNC_NAME "__construct"
-#define ZEND_DESTRUCTOR_FUNC_NAME "__destruct"
-
void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference TSRMLS_DC)
{
zend_op_array op_array;
@@ -938,6 +934,12 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array);
} else if ((function_name->u.constant.value.str.len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)))) {
CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
+ } else if ((function_name->u.constant.value.str.len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)))) {
+ CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
+ } else if ((function_name->u.constant.value.str.len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)))) {
+ CG(active_class_entry)->__get = (zend_function *) CG(active_op_array);
+ } else if ((function_name->u.constant.value.str.len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)))) {
+ CG(active_class_entry)->__set = (zend_function *) CG(active_op_array);
}
} else {
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
@@ -1551,6 +1553,9 @@ static void create_class(HashTable *class_table, char *name, int name_length, ze
new_class_entry->constructor = NULL;
new_class_entry->destructor = NULL;
new_class_entry->clone = NULL;
+ new_class_entry->__get = NULL;
+ new_class_entry->__set = NULL;
+ new_class_entry->__call = NULL;
new_class_entry->create_object = NULL;
new_class_entry->handle_function_call = NULL;
@@ -2050,6 +2055,9 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
new_class_entry->constructor = NULL;
new_class_entry->destructor = NULL;
new_class_entry->clone = NULL;
+ new_class_entry->__get = NULL;
+ new_class_entry->__set = NULL;
+ new_class_entry->__call = NULL;
new_class_entry->create_object = NULL;
new_class_entry->handle_function_call = NULL;
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 69f98864d7..94422bf766 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -710,4 +710,11 @@ int zendlex(znode *zendlval TSRMLS_DC);
END_EXTERN_C()
+#define ZEND_CLONE_FUNC_NAME "__clone"
+#define ZEND_CONSTRUCTOR_FUNC_NAME "__construct"
+#define ZEND_DESTRUCTOR_FUNC_NAME "__destruct"
+#define ZEND_GET_FUNC_NAME "__get"
+#define ZEND_SET_FUNC_NAME "__set"
+#define ZEND_CALL_FUNC_NAME "__call"
+
#endif /* ZEND_COMPILE_H */
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index d14284b242..fb10e0eda0 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -140,7 +140,7 @@ static inline zval **_get_zval_ptr_ptr(znode *node, temp_variable *Ts TSRMLS_DC)
static inline zval **zend_fetch_property_address_inner(zval *object, znode *op2, temp_variable *Ts, int type TSRMLS_DC)
{
zval *prop_ptr = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
- zval **retval;
+ zval **retval = NULL;
zval tmp;
@@ -161,7 +161,9 @@ static inline zval **zend_fetch_property_address_inner(zval *object, znode *op2,
if(Z_OBJ_HT_P(object)->get_property_ptr != NULL) {
retval = Z_OBJ_HT_P(object)->get_property_ptr(object, prop_ptr TSRMLS_CC);
- } else {
+ }
+
+ if(retval == NULL) {
zend_error(E_WARNING, "This object doesn't support property references");
retval = &EG(error_zval_ptr);
}
@@ -321,6 +323,7 @@ static inline void zend_assign_to_object_op(znode *result, znode *op1, znode *op
zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
zval tmp;
zval **retval = &Ts[result->u.var].var.ptr;
+ int have_get_ptr = 0;
Ts[result->u.var].var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
@@ -356,12 +359,17 @@ static inline void zend_assign_to_object_op(znode *result, znode *op1, znode *op
if(Z_OBJ_HT_P(object)->get_property_zval_ptr) {
zval **zptr = Z_OBJ_HT_P(object)->get_property_zval_ptr(object, property TSRMLS_CC);
- SEPARATE_ZVAL_IF_NOT_REF(zptr);
+ if(zptr != NULL) { /* NULL means no success in getting PTR */
+ SEPARATE_ZVAL_IF_NOT_REF(zptr);
- binary_op(*zptr, *zptr, value TSRMLS_CC);
- *retval = *zptr;
- SELECTIVE_PZVAL_LOCK(*retval, result);
- } else {
+ have_get_ptr = 1;
+ binary_op(*zptr, *zptr, value TSRMLS_CC);
+ *retval = *zptr;
+ SELECTIVE_PZVAL_LOCK(*retval, result);
+ }
+ }
+
+ if(!have_get_ptr) {
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_RW TSRMLS_CC);
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
@@ -989,6 +997,7 @@ static void zend_pre_incdec_property(znode *result, znode *op1, znode *op2, temp
zval *object;
zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
zval **retval = &Ts[result->u.var].var.ptr;
+ int have_get_ptr = 0;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
@@ -1006,12 +1015,17 @@ static void zend_pre_incdec_property(znode *result, znode *op1, znode *op2, temp
if(Z_OBJ_HT_P(object)->get_property_zval_ptr) {
zval **zptr = Z_OBJ_HT_P(object)->get_property_zval_ptr(object, property TSRMLS_CC);
- SEPARATE_ZVAL_IF_NOT_REF(zptr);
+ if(zptr != NULL) { /* NULL means no success in getting PTR */
+ SEPARATE_ZVAL_IF_NOT_REF(zptr);
- incdec_op(*zptr);
- *retval = *zptr;
- SELECTIVE_PZVAL_LOCK(*retval, result);
- } else {
+ have_get_ptr = 1;
+ incdec_op(*zptr);
+ *retval = *zptr;
+ SELECTIVE_PZVAL_LOCK(*retval, result);
+ }
+ }
+
+ if(!have_get_ptr) {
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_RW TSRMLS_CC);
SEPARATE_ZVAL_IF_NOT_REF(&z);
incdec_op(z);
@@ -1030,6 +1044,7 @@ static void zend_post_incdec_property(znode *result, znode *op1, znode *op2, tem
zval *object;
zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
zval *retval = &Ts[result->u.var].tmp_var;
+ int have_get_ptr = 0;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
@@ -1045,13 +1060,19 @@ static void zend_post_incdec_property(znode *result, znode *op1, znode *op2, tem
if(Z_OBJ_HT_P(object)->get_property_zval_ptr) {
zval **zptr = Z_OBJ_HT_P(object)->get_property_zval_ptr(object, property TSRMLS_CC);
- SEPARATE_ZVAL_IF_NOT_REF(zptr);
+ if(zptr != NULL) { /* NULL means no success in getting PTR */
+ have_get_ptr = 1;
+ SEPARATE_ZVAL_IF_NOT_REF(zptr);
+
+ *retval = **zptr;
+ zendi_zval_copy_ctor(*retval);
+
+ incdec_op(*zptr);
- *retval = **zptr;
- zendi_zval_copy_ctor(*retval);
+ }
+ }
- incdec_op(*zptr);
- } else {
+ if(!have_get_ptr) {
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_RW TSRMLS_CC);
SEPARATE_ZVAL_IF_NOT_REF(&z);
*retval = *z;
diff --git a/Zend/zend_extensions.h b/Zend/zend_extensions.h
index 3f7e0ebfd3..0e540b72e6 100644
--- a/Zend/zend_extensions.h
+++ b/Zend/zend_extensions.h
@@ -23,7 +23,7 @@
#include "zend_compile.h"
-#define ZEND_EXTENSION_API_NO 20010710
+#define ZEND_EXTENSION_API_NO 220020901
typedef struct _zend_extension_version_info {
int zend_extension_api_no;
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 9c131e2626..1af47b2a27 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -8,6 +8,23 @@
#define DEBUG_OBJECT_HANDLERS 0
+/*
+ __X accessors explanation:
+
+ if we have __get and property that is not part of the properties array is
+ requested, we call __get handler. If it fails, we return uninitialized.
+
+ if we have __set and property that is not part of the properties array is
+ set, we call __set handler. If it fails, we do not change the array.
+
+ for both handlers above, when we are inside __get/__set, no further calls for
+ __get/__set for these objects will be made, to prevent endless recursion and
+ enable accessors to change properties array.
+
+ if we have __call and method which is not part of the class function table is
+ called, we cal __call handler.
+*/
+
static HashTable *zend_std_get_properties(zval *object TSRMLS_DC)
{
zend_object *zobj;
@@ -15,11 +32,109 @@ static HashTable *zend_std_get_properties(zval *object TSRMLS_DC)
return zobj->properties;
}
+static zval *zend_std_call_getter(zval *object, zval *member TSRMLS_DC)
+{
+ zval **call_args[1];
+ zval *retval = NULL;
+ zval __get_name;
+ int call_result;
+
+ /* __get handler is called with two arguments:
+ property name
+ return value for the object (by reference)
+
+ it should return whether the call was successfull or not
+ */
+ INIT_PZVAL(&__get_name);
+ ZVAL_STRINGL(&__get_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1, 0);
+
+ call_args[0] = &member;
+
+ /* go call the __get handler */
+ call_result = call_user_function_ex(NULL,
+ &object,
+ &__get_name,
+ &retval,
+ 1, call_args,
+ 0, NULL TSRMLS_CC);
+
+ /*
+ call_result is if call_user_function gone OK.
+ retval returns the value that is received
+ */
+
+
+ if(call_result == FAILURE) {
+ zend_error(E_ERROR, "Could not call __get handler for class %s", Z_OBJCE_P(object)->name);
+ return NULL;
+ }
+
+ retval->refcount--;
+
+ return retval;
+}
+
+static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_DC)
+{
+ zval **call_args[2];
+ zval *retval = NULL;
+ zval __set_name;
+ int call_result;
+ int ret;
+
+ /* __set handler is called with two arguments:
+ property name
+ value to be set
+
+ it should return whether the call was successfull or not
+ */
+ INIT_PZVAL(&__set_name);
+ ZVAL_STRINGL(&__set_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1, 0);
+
+ call_args[0] = &member;
+ value->refcount++;
+ call_args[1] = &value;
+
+ /* go call the __set handler */
+ call_result = call_user_function_ex(NULL,
+ &object,
+ &__set_name,
+ &retval,
+ 2, call_args,
+ 0, NULL TSRMLS_CC);
+
+ /*
+ call_result is if call_user_function gone OK.
+ retval shows if __get method went OK.
+ */
+
+
+ if(call_result == FAILURE) {
+ zend_error(E_ERROR, "Could not call __set handler for class %s", Z_OBJCE_P(object)->name);
+ return FAILURE;
+ }
+
+ zval_ptr_dtor(&value);
+
+ if (retval && zval_is_true(retval)) {
+ ret = SUCCESS;
+ } else {
+ ret = FAILURE;
+ }
+
+ if(retval) {
+ zval_ptr_dtor(&retval);
+ }
+
+ return ret;
+}
+
zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
{
zend_object *zobj;
zval tmp_member;
zval **retval;
+ zval *rv = NULL;
zobj = Z_OBJ_P(object);
@@ -35,25 +150,38 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
#endif
if (zend_hash_find(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &retval) == FAILURE) {
- switch (type) {
- case BP_VAR_R:
- zend_error(E_NOTICE,"Undefined property: %s", Z_STRVAL_P(member));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval_ptr);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined property: %s", Z_STRVAL_P(member));
- /* break missing intentionally */
- case BP_VAR_W: {
+ if(zobj->ce->__get && !zobj->in_get) {
+ /* have getter - try with it! */
+ zobj->in_get = 1; /* prevent circular getting */
+ rv = zend_std_call_getter(object, member TSRMLS_CC);
+ zobj->in_get = 0;
+
+ if(rv) {
+ retval = &rv;
+ } else {
+ retval = &EG(uninitialized_zval_ptr);
+ }
+ } else {
+ switch (type) {
+ case BP_VAR_R:
+ zend_error(E_NOTICE,"Undefined property: %s", Z_STRVAL_P(member));
+ /* break missing intentionally */
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval_ptr);
+ break;
+ case BP_VAR_RW:
+ zend_error(E_NOTICE,"Undefined property: %s", Z_STRVAL_P(member));
+ /* break missing intentionally */
+ case BP_VAR_W: {
zval *new_zval = &EG(uninitialized_zval);
-
+
new_zval->refcount++;
zend_hash_update(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, &new_zval, sizeof(zval *), (void **) &retval);
- }
+ }
break;
EMPTY_SWITCH_DEFAULT_CASE()
-
+
+ }
}
}
if (member == &tmp_member) {
@@ -67,6 +195,7 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
zend_object *zobj;
zval tmp_member;
zval **variable_ptr;
+ int setter_done = 0;
zobj = Z_OBJ_P(object);
@@ -88,10 +217,21 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
FREE_ZVAL(*variable_ptr);
}
}
+ } else {
+ if(zobj->ce->__set && !zobj->in_set) {
+ zobj->in_set = 1; /* prevent circular setting */
+ if(zend_std_call_setter(object, member, value) != SUCCESS) {
+// zend_error(E_NOTICE,"Cannot set undefined property: %s", Z_STRVAL_P(member));
+ }
+ setter_done = 1;
+ zobj->in_set = 0;
+ }
}
- value->refcount++;
- zend_hash_update(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, &value, sizeof(zval *), NULL);
+ if(!setter_done) {
+ value->refcount++;
+ zend_hash_update(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, &value, sizeof(zval *), NULL);
+ }
if (member == &tmp_member) {
zval_dtor(member);
}
@@ -117,11 +257,19 @@ static zval **zend_std_get_property_ptr(zval *object, zval *member TSRMLS_DC)
#endif
if (zend_hash_find(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &retval) == FAILURE) {
- zval *new_zval = &EG(uninitialized_zval);
+ zval *new_zval;
- zend_error(E_NOTICE, "Undefined property: %s", Z_STRVAL_P(member));
- new_zval->refcount++;
- zend_hash_update(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, &new_zval, sizeof(zval *), (void **) &retval);
+ if(!zobj->ce->__get) {
+ /* we don't have getter - will just add it */
+ new_zval = &EG(uninitialized_zval);
+
+ zend_error(E_NOTICE, "Undefined property: %s", Z_STRVAL_P(member));
+ new_zval->refcount++;
+ zend_hash_update(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, &new_zval, sizeof(zval *), (void **) &retval);
+ } else {
+ /* we do have getter - fail and let it try again with usual get/set */
+ retval = NULL;
+ }
}
if (member == &tmp_member) {
zval_dtor(member);
@@ -148,12 +296,100 @@ static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC)
}
}
+static void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS)
+{
+ zval ***args;
+ zend_internal_function *func = (zend_internal_function *)EG(function_state_ptr)->function;
+ zval method_name, method_args, method_result, __call_name;
+ zval *method_name_ptr, *method_args_ptr, *method_result_ptr;
+ zval **call_args[3];
+ zval *retval = NULL;
+ int i, call_result;
+
+ args = (zval ***)emalloc(ZEND_NUM_ARGS() * sizeof(zval **));
+
+ if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
+ efree(args);
+ zend_error(E_ERROR, "Cannot get arguments for __call");
+ RETURN_FALSE;
+ }
+
+ method_name_ptr = &method_name;
+ INIT_PZVAL(method_name_ptr);
+ ZVAL_STRING(method_name_ptr, func->function_name, 0); /* no dup - it's a copy */
+
+ method_args_ptr = &method_args;
+ INIT_PZVAL(method_args_ptr);
+ array_init(method_args_ptr);
+
+ for(i=0; i<ZEND_NUM_ARGS(); i++) {
+ zval_add_ref(args[i]);
+ add_next_index_zval(method_args_ptr, *args[i]);
+ }
+
+ efree(args);
+
+ method_result_ptr = &method_result;
+ method_result.is_ref = 1;
+ method_result.refcount = 1;
+ ZVAL_NULL(method_result_ptr);
+
+ INIT_PZVAL(&__call_name);
+ ZVAL_STRINGL(&__call_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1, 0);
+
+ /* __call handler is called with three arguments:
+ method name
+ array of method parameters
+ return value for the method (by reference)
+
+ it should return whether the call was successfull or not
+ */
+ call_args[0] = &method_name_ptr;
+ call_args[1] = &method_args_ptr;
+ call_args[2] = &method_result_ptr;
+
+ /* go call the __call handler */
+ call_result = call_user_function_ex(NULL,
+ &this_ptr,
+ &__call_name,
+ &retval,
+ 3, call_args,
+ 0, NULL TSRMLS_CC);
+
+ /* A lot of return values here. Let's sort them out:
+ call_result is if call_user_function gone OK.
+ retval shows if __call method went OK.
+ method_result is the true result of the called method
+ */
+
+
+ if(call_result == FAILURE) {
+ zend_error(E_ERROR, "Could not call __call handler for class %s", Z_OBJCE_P(this_ptr)->name);
+ }
+
+ if (retval && zval_is_true(retval)) {
+ *return_value = method_result;
+ INIT_PZVAL(return_value);
+ } else {
+ zval_dtor(method_result_ptr);
+ zend_error(E_ERROR, "Call to undefined method %s::%s()", Z_OBJCE_P(this_ptr)->name, Z_STRVAL(method_name));
+ }
+ zval_ptr_dtor(&retval);
+
+ /* now destruct all auxiliaries */
+ zval_dtor(method_args_ptr);
+ zval_dtor(method_name_ptr);
+
+ /* destruct the function also, then - we have allocated it in get_method */
+ efree(func);
+}
+
static union _zend_function *zend_std_get_method(zval *object, char *method_name, int method_len TSRMLS_DC)
{
zend_object *zobj;
zend_function *func_method;
char *lc_method_name;
-
+
lc_method_name = do_alloca(method_len+1);
/* Create a zend_copy_str_tolower(dest, src, src_length); */
memcpy(lc_method_name, method_name, method_len+1);
@@ -161,6 +397,17 @@ static union _zend_function *zend_std_get_method(zval *object, char *method_name
zobj = Z_OBJ_P(object);
if(zend_hash_find(&zobj->ce->function_table, lc_method_name, method_len+1, (void **)&func_method) == FAILURE) {
+ if(zobj->ce->__call != NULL) {
+ zend_internal_function *call_user_call = emalloc(sizeof(zend_internal_function));
+ call_user_call->type = ZEND_INTERNAL_FUNCTION;
+ call_user_call->handler = zend_std_call_user_call;
+ call_user_call->arg_types = NULL;
+ call_user_call->scope = NULL;
+ call_user_call->function_name = estrndup(method_name, method_len);
+
+ free_alloca(lc_method_name);
+ return (union _zend_function *)call_user_call;
+ }
zend_error(E_ERROR, "Call to undefined function %s()", method_name);
}
diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c
index 3e253cc406..a6b7579350 100644
--- a/Zend/zend_objects.c
+++ b/Zend/zend_objects.c
@@ -57,6 +57,8 @@ ZEND_API zend_object_value zend_objects_new(zend_object **object, zend_class_ent
(*object)->ce = class_type;
retval.handle = zend_objects_store_put(*object, (zend_objects_store_dtor_t) zend_objects_destroy_object, NULL TSRMLS_CC);
retval.handlers = &std_object_handlers;
+ (*object)->in_get = 0;
+ (*object)->in_set = 0;
return retval;
}