summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
Diffstat (limited to 'Zend')
-rw-r--r--Zend/zend_compile.c125
-rw-r--r--Zend/zend_compile.h19
-rw-r--r--Zend/zend_execute.c304
-rw-r--r--Zend/zend_object_handlers.c20
-rw-r--r--Zend/zend_object_handlers.h5
5 files changed, 450 insertions, 23 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 997848d350..b5943c1464 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -181,17 +181,85 @@ void zend_do_unary_op(int op, znode *result, znode *op1 TSRMLS_DC)
SET_UNUSED(opline->op2);
}
+#define MAKE_NOP(opline) { opline->opcode = ZEND_NOP; memset(&opline->result,0,sizeof(znode)); memset(&opline->op1,0,sizeof(znode)); memset(&opline->op2,0,sizeof(znode)); opline->result.op_type=opline->op1.op_type=opline->op2.op_type=IS_UNUSED; }
+
+static void zend_replace_object_fetch(zend_op *last_op, znode *value TSRMLS_DC)
+{
+ if(value->op_type != IS_VAR) {
+ last_op->opcode = ZEND_MAKE_VAR;
+ last_op->result.op_type = IS_VAR;
+ last_op->result.u.EA.type = 0;
+ last_op->result.u.var = get_temporary_variable(CG(active_op_array));
+ last_op->op1 = *value;
+ SET_UNUSED(last_op->op2);
+ value->op_type = IS_VAR;
+ value->u.EA.type = 0;
+ value->u.var = last_op->result.u.var;
+ } else {
+ MAKE_NOP(last_op);
+ }
+}
void zend_do_binary_assign_op(int op, znode *result, znode *op1, znode *op2 TSRMLS_DC)
{
+ int last_op_number = get_next_op_number(CG(active_op_array))-1;
+ zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number];
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = op;
+ if(last_op->opcode == ZEND_FETCH_OBJ_RW) {
+
+ switch(op) {
+ case ZEND_ASSIGN_ADD:
+ opline->opcode = ZEND_ASSIGN_ADD_OBJ;
+ break;
+ case ZEND_ASSIGN_SUB:
+ opline->opcode = ZEND_ASSIGN_SUB_OBJ;
+ break;
+ case ZEND_ASSIGN_MUL:
+ opline->opcode = ZEND_ASSIGN_MUL_OBJ;
+ break;
+ case ZEND_ASSIGN_DIV:
+ opline->opcode = ZEND_ASSIGN_DIV_OBJ;
+ break;
+ case ZEND_ASSIGN_MOD:
+ opline->opcode = ZEND_ASSIGN_MOD_OBJ;
+ break;
+ case ZEND_ASSIGN_SL:
+ opline->opcode = ZEND_ASSIGN_SL_OBJ;
+ break;
+ case ZEND_ASSIGN_SR:
+ opline->opcode = ZEND_ASSIGN_SR_OBJ;
+ break;
+ case ZEND_ASSIGN_CONCAT:
+ opline->opcode = ZEND_ASSIGN_CONCAT_OBJ;
+ break;
+ case ZEND_ASSIGN_BW_OR:
+ opline->opcode = ZEND_ASSIGN_BW_OR_OBJ;
+ break;
+ case ZEND_ASSIGN_BW_AND:
+ opline->opcode = ZEND_ASSIGN_BW_AND_OBJ;
+ break;
+ case ZEND_ASSIGN_BW_XOR:
+ opline->opcode = ZEND_ASSIGN_BW_XOR_OBJ;
+ break;
+ default:
+ zend_error(E_ERROR, "Unknown binary op opcode %d", op);
+ }
+
+ opline->op2 = last_op->op2;
+ opline->op1 = last_op->op1;
+ zend_replace_object_fetch(last_op, op2 TSRMLS_CC);
+ opline->extended_value = op2->u.var;
+
+ } else {
+ opline->opcode = op;
+ opline->op1 = *op1;
+ opline->op2 = *op2;
+ }
+
opline->result.op_type = IS_VAR;
opline->result.u.EA.type = 0;
opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *op1;
- opline->op2 = *op2;
*result = opline->result;
}
@@ -316,14 +384,26 @@ void zend_do_echo(znode *arg TSRMLS_DC)
void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC)
{
+ int last_op_number = get_next_op_number(CG(active_op_array))-1;
+ zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number];
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_ASSIGN;
+ if(last_op->opcode == ZEND_FETCH_OBJ_W) {
+ opline->opcode = ZEND_ASSIGN_OBJ;
+ opline->op1 = last_op->op1;
+ opline->op2 = last_op->op2;
+
+ zend_replace_object_fetch(last_op, value TSRMLS_CC);
+
+ opline->extended_value = value->u.var;
+ } else {
+ opline->opcode = ZEND_ASSIGN;
+ opline->op1 = *variable;
+ opline->op2 = *value;
+ }
opline->result.op_type = IS_VAR;
opline->result.u.EA.type = 0;
opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *variable;
- opline->op2 = *value;
*result = opline->result;
}
@@ -447,28 +527,49 @@ void zend_do_for_end(znode *second_semicolon_token TSRMLS_DC)
void zend_do_pre_incdec(znode *result, znode *op1, int op TSRMLS_DC)
{
+ int last_op_number = get_next_op_number(CG(active_op_array))-1;
+ zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number];
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = op;
+ if(last_op->opcode == ZEND_FETCH_OBJ_RW) {
+ opline->opcode = (op==ZEND_PRE_INC)?ZEND_PRE_INC_OBJ:ZEND_PRE_DEC_OBJ;
+ opline->op1 = last_op->op1;
+ opline->op2 = last_op->op2;
+
+ MAKE_NOP(last_op);
+ } else {
+ opline->opcode = op;
+ opline->op1 = *op1;
+ SET_UNUSED(opline->op2);
+ }
+
opline->result.op_type = IS_VAR;
opline->result.u.EA.type = 0;
opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *op1;
*result = opline->result;
- SET_UNUSED(opline->op2);
}
void zend_do_post_incdec(znode *result, znode *op1, int op TSRMLS_DC)
{
+ int last_op_number = get_next_op_number(CG(active_op_array))-1;
+ zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number];
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = op;
+ if(last_op->opcode == ZEND_FETCH_OBJ_RW) {
+ opline->opcode = (op==ZEND_POST_INC)?ZEND_POST_INC_OBJ:ZEND_POST_DEC_OBJ;
+ opline->op1 = last_op->op1;
+ opline->op2 = last_op->op2;
+
+ MAKE_NOP(last_op);
+ } else {
+ opline->opcode = op;
+ opline->op1 = *op1;
+ SET_UNUSED(opline->op2);
+ }
opline->result.op_type = IS_TMP_VAR;
opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *op1;
*result = opline->result;
- SET_UNUSED(opline->op2);
}
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 4b00f5727b..1a24312e4c 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -559,6 +559,25 @@ int zendlex(znode *zendlval TSRMLS_DC);
#define ZEND_IMPORT_CLASS 117
#define ZEND_IMPORT_CONST 118
+#define ZEND_ASSIGN_ADD_OBJ 121
+#define ZEND_ASSIGN_SUB_OBJ 122
+#define ZEND_ASSIGN_MUL_OBJ 123
+#define ZEND_ASSIGN_DIV_OBJ 124
+#define ZEND_ASSIGN_MOD_OBJ 125
+#define ZEND_ASSIGN_SL_OBJ 126
+#define ZEND_ASSIGN_SR_OBJ 127
+#define ZEND_ASSIGN_CONCAT_OBJ 128
+#define ZEND_ASSIGN_BW_OR_OBJ 129
+#define ZEND_ASSIGN_BW_AND_OBJ 130
+#define ZEND_ASSIGN_BW_XOR_OBJ 131
+
+#define ZEND_PRE_INC_OBJ 132
+#define ZEND_PRE_DEC_OBJ 133
+#define ZEND_POST_INC_OBJ 134
+#define ZEND_POST_DEC_OBJ 135
+
+#define ZEND_ASSIGN_OBJ 136
+#define ZEND_MAKE_VAR 137
/* end of block */
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 4c9dea3cb5..2a44352254 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -39,10 +39,14 @@
switch (opcode) { \
case ZEND_PRE_INC: \
case ZEND_POST_INC: \
+ case ZEND_PRE_INC_OBJ: \
+ case ZEND_POST_INC_OBJ: \
(op) = increment_function; \
break; \
case ZEND_PRE_DEC: \
case ZEND_POST_DEC: \
+ case ZEND_PRE_DEC_OBJ: \
+ case ZEND_POST_DEC_OBJ: \
(op) = decrement_function; \
break; \
default: \
@@ -184,7 +188,12 @@ static inline zval **zend_fetch_property_address_inner(zval *object, znode *op2,
break;
}
- retval = Z_OBJ_HT_P(object)->get_property_ptr(object, prop_ptr TSRMLS_CC);
+ 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 {
+ zend_error(E_WARNING, "This object doesn't support property references");
+ retval = &EG(error_zval_ptr);
+ }
if (prop_ptr == &tmp) {
zval_dtor(prop_ptr);
@@ -268,6 +277,134 @@ void zend_assign_to_variable_reference(znode *result, zval **variable_ptr_ptr, z
}
}
+static inline void make_real_object(zval **object_ptr) {
+ if ((*object_ptr)->type == IS_NULL
+ || ((*object_ptr)->type == IS_BOOL && (*object_ptr)->value.lval==0)
+ || ((*object_ptr)->type == IS_STRING && (*object_ptr)->value.str.len == 0)) {
+ if (!PZVAL_IS_REF(*object_ptr)) {
+ SEPARATE_ZVAL(object_ptr);
+ }
+ zend_error(E_NOTICE, "Creating default object from empty value");
+ object_init(*object_ptr);
+ }
+}
+
+static inline void zend_assign_to_object(znode *result, znode *op1, znode *op2, zval *value, temp_variable *Ts TSRMLS_DC)
+{
+ zval **object_ptr = get_zval_ptr_ptr(op1, Ts, BP_VAR_W);
+ zval *object;
+ zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
+ zval tmp;
+ zval **retval = &Ts[result->u.var].var.ptr;
+
+ make_real_object(object_ptr);
+ object = *object_ptr;
+
+ if (object->type != IS_OBJECT) {
+ zend_error(E_WARNING, "Attempt to assign property of non-object");
+ FREE_OP(Ts, op2, EG(free_op2));
+ *retval = EG(uninitialized_zval_ptr);
+
+ SELECTIVE_PZVAL_LOCK(*retval, result);
+ return;
+ }
+
+ /* here we are sure we are dealing with an object */
+ switch (op2->op_type) {
+ case IS_CONST:
+ /* already a constant string */
+ break;
+ case IS_VAR:
+ tmp = *property;
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ property = &tmp;
+ break;
+ case IS_TMP_VAR:
+ convert_to_string(property);
+ break;
+ }
+
+ /* here property is a string */
+ PZVAL_UNLOCK(value);
+
+ Z_OBJ_HT_P(object)->write_property(object, property, value TSRMLS_CC);
+ if (property == &tmp) {
+ zval_dtor(property);
+ }
+
+ FREE_OP(Ts, op2, EG(free_op2));
+ if (result) {
+ Ts[result->u.var].var.ptr = value;
+ Ts[result->u.var].var.ptr_ptr = NULL; /* see if we can nuke this */
+ SELECTIVE_PZVAL_LOCK(value, result);
+ }
+}
+
+static inline void zend_assign_to_object_op(znode *result, znode *op1, znode *op2, zval *value, temp_variable *Ts, int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC) TSRMLS_DC) {
+ zval **object_ptr = get_zval_ptr_ptr(op1, Ts, BP_VAR_W);
+ zval *object;
+ zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
+ zval tmp;
+ zval **retval = &Ts[result->u.var].var.ptr;
+
+ Ts[result->u.var].var.ptr_ptr = NULL;
+ make_real_object(object_ptr);
+ object = *object_ptr;
+
+ if (object->type != IS_OBJECT) {
+ zend_error(E_WARNING, "Attempt to assign property of non-object");
+ FREE_OP(Ts, op2, EG(free_op2));
+ *retval = EG(uninitialized_zval_ptr);
+
+ SELECTIVE_PZVAL_LOCK(*retval, result);
+ return;
+ }
+
+ /* here we are sure we are dealing with an object */
+ switch (op2->op_type) {
+ case IS_CONST:
+ /* already a constant string */
+ break;
+ case IS_VAR:
+ tmp = *property;
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ property = &tmp;
+ break;
+ case IS_TMP_VAR:
+ convert_to_string(property);
+ break;
+ }
+
+ /* here property is a string */
+ PZVAL_UNLOCK(value);
+
+ 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);
+
+ binary_op(*zptr, *zptr, value);
+ *retval = *zptr;
+ SELECTIVE_PZVAL_LOCK(*retval, result);
+ } else {
+ 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);
+ Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ *retval = z;
+ SELECTIVE_PZVAL_LOCK(*retval, result);
+ if(z->refcount <= 1) {
+ zval_dtor(z);
+ }
+ }
+
+ if (property == &tmp) {
+ zval_dtor(property);
+ }
+
+ FREE_OP(Ts, op2, EG(free_op2));
+}
static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2, zval *value, int type, temp_variable *Ts TSRMLS_DC)
{
@@ -884,6 +1021,89 @@ static void zend_fetch_property_address_read(znode *result, znode *op1, znode *o
return;
}
+static void zend_pre_incdec_property(znode *result, znode *op1, znode *op2, temp_variable * Ts, int (*incdec_op)(zval *) TSRMLS_DC)
+{
+ zval **object_ptr = get_zval_ptr_ptr(op1, Ts, BP_VAR_W);
+ zval *object;
+ zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
+ zval **retval = &Ts[result->u.var].var.ptr;
+
+ make_real_object(object_ptr);
+ object = *object_ptr;
+
+ if (object->type != IS_OBJECT) {
+ zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
+ FREE_OP(Ts, op2, EG(free_op2));
+ *retval = EG(uninitialized_zval_ptr);
+
+ SELECTIVE_PZVAL_LOCK(*retval, result);
+ return;
+ }
+
+ /* here we are sure we are dealing with an object */
+
+ 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);
+
+ incdec_op(*zptr);
+ *retval = *zptr;
+ SELECTIVE_PZVAL_LOCK(*retval, result);
+ } else {
+ 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);
+ Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ if(z->refcount <= 1) {
+ zval_dtor(z);
+ }
+ }
+
+ FREE_OP(Ts, op2, EG(free_op2));
+}
+
+static void zend_post_incdec_property(znode *result, znode *op1, znode *op2, temp_variable * Ts, int (*incdec_op)(zval *) TSRMLS_DC)
+{
+ zval **object_ptr = get_zval_ptr_ptr(op1, Ts, BP_VAR_W);
+ zval *object;
+ zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
+ zval *retval = &Ts[result->u.var].tmp_var;
+
+ make_real_object(object_ptr);
+ object = *object_ptr;
+
+ if (object->type != IS_OBJECT) {
+ zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
+ FREE_OP(Ts, op2, EG(free_op2));
+ *retval = *EG(uninitialized_zval_ptr);
+ return;
+ }
+
+ /* here we are sure we are dealing with an object */
+
+ 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);
+
+ *retval = **zptr;
+ zendi_zval_copy_ctor(*retval);
+
+ incdec_op(*zptr);
+ } else {
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_RW TSRMLS_CC);
+ SEPARATE_ZVAL_IF_NOT_REF(&z);
+ *retval = *z;
+ zendi_zval_copy_ctor(*retval);
+ incdec_op(z);
+ Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ if(z->refcount <= 1) {
+ zval_dtor(z);
+ }
+ }
+
+ FREE_OP(Ts, op2, EG(free_op2));
+}
+
#if ZEND_INTENSIVE_DEBUGGING
@@ -1102,6 +1322,59 @@ binary_assign_op_addr: {
AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var);
}
NEXT_OPCODE();
+
+ case ZEND_ASSIGN_ADD_OBJ:
+ EG(binary_op) = add_function;
+ goto binary_assign_op_addr_obj;
+ case ZEND_ASSIGN_SUB_OBJ:
+ EG(binary_op) = sub_function;
+ goto binary_assign_op_addr_obj;
+ case ZEND_ASSIGN_MUL_OBJ:
+ EG(binary_op) = mul_function;
+ goto binary_assign_op_addr_obj;
+ case ZEND_ASSIGN_DIV_OBJ:
+ EG(binary_op) = div_function;
+ goto binary_assign_op_addr_obj;
+ case ZEND_ASSIGN_MOD_OBJ:
+ EG(binary_op) = mod_function;
+ goto binary_assign_op_addr_obj;
+ case ZEND_ASSIGN_SL_OBJ:
+ EG(binary_op) = shift_left_function;
+ goto binary_assign_op_addr_obj;
+ case ZEND_ASSIGN_SR_OBJ:
+ EG(binary_op) = shift_right_function;
+ goto binary_assign_op_addr_obj;
+ case ZEND_ASSIGN_CONCAT_OBJ:
+ EG(binary_op) = concat_function;
+ goto binary_assign_op_addr_obj;
+ case ZEND_ASSIGN_BW_OR_OBJ:
+ EG(binary_op) = bitwise_or_function;
+ goto binary_assign_op_addr_obj;
+ case ZEND_ASSIGN_BW_AND_OBJ:
+ EG(binary_op) = bitwise_and_function;
+ goto binary_assign_op_addr_obj;
+ case ZEND_ASSIGN_BW_XOR_OBJ:
+ EG(binary_op) = bitwise_xor_function;
+ /* Fall through */
+binary_assign_op_addr_obj:
+ zend_assign_to_object_op(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts)[EX(opline)->extended_value].var.ptr, EX(Ts), EG(binary_op) TSRMLS_CC);
+ NEXT_OPCODE();
+ case ZEND_PRE_INC_OBJ:
+ case ZEND_PRE_DEC_OBJ: {
+ int (*incdec_op)(zval *op);
+
+ get_incdec_op(incdec_op, EX(opline)->opcode);
+ zend_pre_incdec_property(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), incdec_op TSRMLS_CC);
+ }
+ NEXT_OPCODE();
+ case ZEND_POST_INC_OBJ:
+ case ZEND_POST_DEC_OBJ: {
+ int (*incdec_op)(zval *op);
+
+ get_incdec_op(incdec_op, EX(opline)->opcode);
+ zend_post_incdec_property(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), incdec_op TSRMLS_CC);
+ }
+ NEXT_OPCODE();
case ZEND_PRE_INC:
case ZEND_PRE_DEC:
case ZEND_POST_INC:
@@ -1261,6 +1534,35 @@ binary_assign_op_addr: {
zend_fetch_dimension_address_from_tmp_var(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts) TSRMLS_CC);
AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var);
NEXT_OPCODE();
+ case ZEND_MAKE_VAR: {
+ zval *value, *value2;
+
+ value = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
+ switch(EX(opline)->op1.op_type) {
+ case IS_TMP_VAR:
+ value2 = value;
+ ALLOC_ZVAL(value);
+ *value = *value2;
+ value->is_ref = 0;
+ value->refcount = 0; /* lock will increase this */
+ break;
+ case IS_CONST:
+ value2 = value;
+ ALLOC_ZVAL(value);
+ *value = *value2;
+ zval_copy_ctor(value);
+ value->is_ref = 0;
+ value->refcount = 0; /* lock will increase this */
+ break;
+ }
+
+ EX(Ts)[EX(opline)->result.u.var].var.ptr = value;
+ PZVAL_LOCK(EX(Ts)[EX(opline)->result.u.var].var.ptr);
+ }
+ NEXT_OPCODE();
+ case ZEND_ASSIGN_OBJ:
+ zend_assign_to_object(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts)[EX(opline)->extended_value].var.ptr, EX(Ts) TSRMLS_CC);
+ NEXT_OPCODE();
case ZEND_ASSIGN: {
zval *value;
value = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R);
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 9db2cbce5a..a2a7a5665c 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -65,7 +65,7 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
{
zend_object *zobj;
zval tmp_member;
- zval *variable_ptr;
+ zval **variable_ptr;
zobj = Z_GET_OBJ(object);
@@ -77,19 +77,20 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
}
if (zend_hash_find(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member), (void **) &variable_ptr) == SUCCESS) {
- if (variable_ptr == EG(error_zval_ptr) || member == EG(error_zval_ptr)) {
+ if (*variable_ptr == EG(error_zval_ptr) || member == EG(error_zval_ptr)) {
/* variable_ptr = EG(uninitialized_zval_ptr); */
/* } else if (variable_ptr==&EG(uninitialized_zval) || variable_ptr!=value_ptr) { */
- } else if (variable_ptr != value) {
- variable_ptr->refcount--;
- if (variable_ptr->refcount == 0) {
- zendi_zval_dtor(*variable_ptr);
- FREE_ZVAL(variable_ptr);
+ } else if (*variable_ptr != value) {
+ (*variable_ptr)->refcount--;
+ if ((*variable_ptr)->refcount == 0) {
+ zendi_zval_dtor(**variable_ptr);
+ FREE_ZVAL(*variable_ptr);
}
}
}
- zend_hash_update(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, &value, sizeof(zval *), NULL);
+ 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,7 +118,7 @@ static zval **zend_std_get_property_ptr(zval *object, zval *member TSRMLS_DC)
if (zend_hash_find(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &retval) == FAILURE) {
zval *new_zval = &EG(uninitialized_zval);
- // zend_error(E_NOTICE, "Undefined property: %s", Z_STRVAL_P(member));
+ 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);
}
@@ -243,6 +244,7 @@ zend_object_handlers std_object_handlers = {
zend_std_read_property, /* read_property */
zend_std_write_property, /* write_property */
zend_std_get_property_ptr, /* get_property_ptr */
+ zend_std_get_property_ptr, /* get_property_zval_ptr */
NULL, /* get */
NULL, /* set */
zend_std_has_property, /* has_property */
diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h
index 21140956ca..f264187c9a 100644
--- a/Zend/zend_object_handlers.h
+++ b/Zend/zend_object_handlers.h
@@ -9,7 +9,9 @@ typedef void (*zend_object_write_property_t)(zval *object, zval *member, zval *v
/* Used to set property of the object */
typedef zval **(*zend_object_get_property_ptr_t)(zval *object, zval *member TSRMLS_DC);
-/* Used to create pointer to the property of the object, for future r/w access */
+/* Used to create pointer to the property of the object, for future r/w access via get/set */
+typedef zval **(*zend_object_get_property_zval_ptr_t)(zval *object, zval *member TSRMLS_DC);
+/* Used to create pointer to the property of the object, for future direct r/w access */
typedef void (*zend_object_set_t)(zval **property, zval *value TSRMLS_DC);
/* Used to set object value (most probably used in combination with
typedef the result of the get_property_ptr) */
@@ -54,6 +56,7 @@ typedef struct _zend_object_handlers {
zend_object_read_property_t read_property;
zend_object_write_property_t write_property;
zend_object_get_property_ptr_t get_property_ptr;
+ zend_object_get_property_zval_ptr_t get_property_zval_ptr;
zend_object_get_t get;
zend_object_set_t set;
zend_object_has_property_t has_property;