From: Dmitry Stogov Date: Wed, 2 Feb 2005 07:19:22 +0000 (+0000) Subject: Fixed bugs #29767 and #31683 (__get and __set methods must not modify property name). X-Git-Tag: RELEASE_0_2~111 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fd4fe1c8d32e40ee25a0e7dcc19e8caa33006165;p=php Fixed bugs #29767 and #31683 (__get and __set methods must not modify property name). --- diff --git a/Zend/tests/bug31683.phpt b/Zend/tests/bug31683.phpt new file mode 100644 index 0000000000..4e0159d6c2 --- /dev/null +++ b/Zend/tests/bug31683.phpt @@ -0,0 +1,97 @@ +--TEST-- +Bug #31683 (changes to $name in __get($name) override future parameters) +--SKIPIF-- + +--FILE-- +ok("ok"); + $foo->ok; + $foo->ok = "ok"; + $x = $foo["ok"]; + $foo["ok"] = "ok"; + isset($foo["ok"]); + unset($foo["ok"]); +// $foo[]; + $foo[] = "ok"; +// isset($foo[]); +// unset($foo[]); + $foo->$a; + echo "---\n"; +} +?> +--EXPECT-- +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +NULL +string(2) "ok" +string(2) "ok" +--- +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +string(2) "ok" +NULL +string(2) "ok" +string(2) "ok" +--- diff --git a/Zend/zend.h b/Zend/zend.h index 0ec9fd3c14..c9cb485233 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -605,6 +605,20 @@ END_EXTERN_C() (*ppzv_dest)->refcount = refcount; \ } +#define SEPARATE_ARG_IF_REF(varptr) \ + if (PZVAL_IS_REF(varptr)) { \ + zval *original_var = varptr; \ + ALLOC_ZVAL(varptr); \ + varptr->value = original_var->value; \ + varptr->type = original_var->type; \ + varptr->is_ref = 0; \ + varptr->refcount = 1; \ + zval_copy_ctor(varptr); \ + } else { \ + varptr->refcount++; \ + } + + #define ZEND_MAX_RESERVED_RESOURCES 4 #include "zend_variables.h" diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index f7e54e5a16..21f879adc1 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -66,8 +66,13 @@ static zval *zend_std_call_getter(zval *object, zval *member TSRMLS_DC) it should return whether the call was successfull or not */ + + SEPARATE_ARG_IF_REF(member); + zend_call_method_with_1_params(&object, ce, &ce->__get, ZEND_GET_FUNC_NAME, &retval, member); + zval_ptr_dtor(&member); + if (retval) { retval->refcount--; } @@ -80,7 +85,8 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_D zval *retval = NULL; int ret; zend_class_entry *ce = Z_OBJCE_P(object); - + + SEPARATE_ARG_IF_REF(member); value->refcount++; /* __set handler is called with two arguments: @@ -91,6 +97,7 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_D */ zend_call_method_with_2_params(&object, ce, &ce->__set, ZEND_SET_FUNC_NAME, &retval, member, value); + zval_ptr_dtor(&member); zval_ptr_dtor(&value); if (retval && zend_is_true(retval)) { @@ -334,12 +341,14 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) { if(offset == NULL) { /* [] construct */ - zval offset_null; - INIT_ZVAL(offset_null); - offset = &offset_null; + ALLOC_INIT_ZVAL(offset); + } else { + SEPARATE_ARG_IF_REF(offset); } zend_call_method_with_1_params(&object, ce, NULL, "offsetget", &retval, offset); + zval_ptr_dtor(&offset); + if (!retval) { if (!EG(exception)) { zend_error(E_ERROR, "Undefined offset for object of type %s used as array", ce->name); @@ -361,14 +370,15 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) static void zend_std_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) { zend_class_entry *ce = Z_OBJCE_P(object); - zval tmp; - + if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) { if (!offset) { - INIT_ZVAL(tmp); - offset = &tmp; + ALLOC_INIT_ZVAL(offset); + } else { + SEPARATE_ARG_IF_REF(offset); } zend_call_method_with_2_params(&object, ce, NULL, "offsetset", NULL, offset, value); + zval_ptr_dtor(&offset); } else { zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name); } @@ -382,7 +392,9 @@ static int zend_std_has_dimension(zval *object, zval *offset, int check_empty TS int result; if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) { + SEPARATE_ARG_IF_REF(offset); zend_call_method_with_1_params(&object, ce, NULL, "offsetexists", &retval, offset); + zval_ptr_dtor(&offset); result = i_zend_is_true(retval); zval_ptr_dtor(&retval); return result; @@ -467,7 +479,9 @@ static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC) zval *retval; if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) { + SEPARATE_ARG_IF_REF(offset); zend_call_method_with_1_params(&object, ce, NULL, "offsetunset", &retval, offset); + zval_ptr_dtor(&offset); zval_ptr_dtor(&retval); } else { zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);