diff options
-rw-r--r-- | Zend/tests/bug75420.10.phpt | 21 | ||||
-rw-r--r-- | Zend/tests/bug75420.11.phpt | 20 | ||||
-rw-r--r-- | Zend/tests/bug75420.12.phpt | 21 | ||||
-rw-r--r-- | Zend/tests/bug75420.13.phpt | 20 | ||||
-rw-r--r-- | Zend/tests/bug75420.14.phpt | 20 | ||||
-rw-r--r-- | Zend/tests/bug75420.15.phpt | 20 | ||||
-rw-r--r-- | Zend/tests/bug75420.16.phpt | 20 | ||||
-rw-r--r-- | Zend/tests/bug75420.9.phpt | 20 | ||||
-rw-r--r-- | Zend/zend_object_handlers.c | 59 |
9 files changed, 198 insertions, 23 deletions
diff --git a/Zend/tests/bug75420.10.phpt b/Zend/tests/bug75420.10.phpt new file mode 100644 index 0000000000..c2ae3aa55d --- /dev/null +++ b/Zend/tests/bug75420.10.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #75420.10 (Indirect modification of magic method argument) +--FILE-- +<?php +class Test implements ArrayAccess { + public function offsetExists($x) { $GLOBALS["name"] = 24; return true; } + public function offsetGet($x) { var_dump($x); return 42; } + public function offsetSet($x, $y) { } + public function offsetUnset($x) { } +} + +$obj = new Test; +$name = "foo"; +$name = str_repeat($name, 2); +var_dump($obj[$name] ?? 12); +var_dump($name); +?> +--EXPECT-- +string(6) "foofoo" +int(42) +int(24) diff --git a/Zend/tests/bug75420.11.phpt b/Zend/tests/bug75420.11.phpt new file mode 100644 index 0000000000..1ec623e41c --- /dev/null +++ b/Zend/tests/bug75420.11.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #75420.11 (Indirect modification of magic method argument) +--FILE-- +<?php +class Test implements ArrayAccess { + public function offsetExists($x) { $GLOBALS["name"] = 24; return true; } + public function offsetGet($x) { var_dump($x); return 42; } + public function offsetSet($x, $y) { } + public function offsetUnset($x) { } +} + +$obj = new Test; +$name = "foo"; +var_dump(empty($obj[$name])); +var_dump($name); +?> +--EXPECT-- +string(3) "foo" +bool(false) +int(24) diff --git a/Zend/tests/bug75420.12.phpt b/Zend/tests/bug75420.12.phpt new file mode 100644 index 0000000000..7ed6f1474b --- /dev/null +++ b/Zend/tests/bug75420.12.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #75420.12 (Indirect modification of magic method argument) +--FILE-- +<?php +class Test implements ArrayAccess { + public function offsetExists($x) { $GLOBALS["name"] = 24; return true; } + public function offsetGet($x) { var_dump($x); return 42; } + public function offsetSet($x, $y) { } + public function offsetUnset($x) { } +} + +$obj = new Test; +$name = "foo"; +$name = str_repeat($name, 2); +var_dump(empty($obj[$name])); +var_dump($name); +?> +--EXPECT-- +string(6) "foofoo" +bool(false) +int(24) diff --git a/Zend/tests/bug75420.13.phpt b/Zend/tests/bug75420.13.phpt new file mode 100644 index 0000000000..38031badd7 --- /dev/null +++ b/Zend/tests/bug75420.13.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #75420.13 (Indirect modification of magic method argument) +--FILE-- +<?php +class Test implements ArrayAccess { + public function offsetExists($x) { $GLOBALS["obj"] = 24; return true; } + public function offsetGet($x) { var_dump($x); return 42; } + public function offsetSet($x, $y) { } + public function offsetUnset($x) { } +} + +$obj = new Test; +$name = "foo"; +var_dump($obj[$name] ?? 12); +var_dump($obj); +?> +--EXPECT-- +string(3) "foo" +int(42) +int(24) diff --git a/Zend/tests/bug75420.14.phpt b/Zend/tests/bug75420.14.phpt new file mode 100644 index 0000000000..07fb2cd984 --- /dev/null +++ b/Zend/tests/bug75420.14.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #75420.14 (Indirect modification of magic method argument) +--FILE-- +<?php +class Test implements ArrayAccess { + public function offsetExists($x) { $GLOBALS["obj"] = 24; return true; } + public function offsetGet($x) { var_dump($x); return 42; } + public function offsetSet($x, $y) { } + public function offsetUnset($x) { } +} + +$obj = new Test; +$name = "foo"; +var_dump(empty($obj[$name])); +var_dump($obj); +?> +--EXPECT-- +string(3) "foo" +bool(false) +int(24) diff --git a/Zend/tests/bug75420.15.phpt b/Zend/tests/bug75420.15.phpt new file mode 100644 index 0000000000..f747b4c887 --- /dev/null +++ b/Zend/tests/bug75420.15.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #75420.15 (Indirect modification of magic method argument) +--FILE-- +<?php +class Test implements ArrayAccess { + public function offsetExists($x) { } + public function offsetGet($x) { } + public function offsetSet($x, $y) { $GLOBALS["name"] = 24; var_dump($x); } + public function offsetUnset($x) { } +} + +$obj = new Test; +$name = "foo"; +$name = str_repeat($name, 2); +$obj[$name] = 1; +var_dump($name); +?> +--EXPECT-- +string(6) "foofoo" +int(24) diff --git a/Zend/tests/bug75420.16.phpt b/Zend/tests/bug75420.16.phpt new file mode 100644 index 0000000000..6c3982eacc --- /dev/null +++ b/Zend/tests/bug75420.16.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #75420.16 (Indirect modification of magic method argument) +--FILE-- +<?php +class Test implements ArrayAccess { + public function offsetExists($x) { } + public function offsetGet($x) { } + public function offsetSet($x, $y) { $GLOBALS["obj"] = 24; var_dump($this); } + public function offsetUnset($x) { } +} + +$obj = new Test; +$name = "foo"; +$obj[$name] = 1; +var_dump($obj); +?> +--EXPECT-- +object(Test)#1 (0) { +} +int(24) diff --git a/Zend/tests/bug75420.9.phpt b/Zend/tests/bug75420.9.phpt new file mode 100644 index 0000000000..d83878e773 --- /dev/null +++ b/Zend/tests/bug75420.9.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #75420.9 (Indirect modification of magic method argument) +--FILE-- +<?php +class Test implements ArrayAccess { + public function offsetExists($x) { $GLOBALS["name"] = 24; return true; } + public function offsetGet($x) { var_dump($x); return 42; } + public function offsetSet($x, $y) { } + public function offsetUnset($x) { } +} + +$obj = new Test; +$name = "foo"; +var_dump($obj[$name] ?? 12); +var_dump($name); +?> +--EXPECT-- +string(3) "foo" +int(42) +int(24) diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 8028b2ee5b..3b86a1a6eb 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -734,34 +734,38 @@ exit: zval *zend_std_read_dimension(zval *object, zval *offset, int type, zval *rv) /* {{{ */ { zend_class_entry *ce = Z_OBJCE_P(object); - zval tmp; + zval tmp_offset, tmp_object; if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) { if (offset == NULL) { /* [] construct */ - ZVAL_NULL(&tmp); - offset = &tmp; + ZVAL_NULL(&tmp_offset); } else { - SEPARATE_ARG_IF_REF(offset); + ZVAL_DEREF(offset); + ZVAL_COPY(&tmp_offset, offset); } + ZVAL_COPY(&tmp_object, object); if (type == BP_VAR_IS) { - zend_call_method_with_1_params(object, ce, NULL, "offsetexists", rv, offset); + zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetexists", rv, &tmp_offset); if (UNEXPECTED(Z_ISUNDEF_P(rv))) { - zval_ptr_dtor(offset); + zval_ptr_dtor(&tmp_object); + zval_ptr_dtor(&tmp_offset); return NULL; } if (!i_zend_is_true(rv)) { - zval_ptr_dtor(offset); + zval_ptr_dtor(&tmp_object); + zval_ptr_dtor(&tmp_offset); zval_ptr_dtor(rv); return &EG(uninitialized_zval); } zval_ptr_dtor(rv); } - zend_call_method_with_1_params(object, ce, NULL, "offsetget", rv, offset); + zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetget", rv, &tmp_offset); - zval_ptr_dtor(offset); + zval_ptr_dtor(&tmp_object); + zval_ptr_dtor(&tmp_offset); if (UNEXPECTED(Z_TYPE_P(rv) == IS_UNDEF)) { if (UNEXPECTED(!EG(exception))) { @@ -780,17 +784,19 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type, zval *rv) /* static void zend_std_write_dimension(zval *object, zval *offset, zval *value) /* {{{ */ { zend_class_entry *ce = Z_OBJCE_P(object); - zval tmp; + zval tmp_offset, tmp_object; if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) { if (!offset) { - ZVAL_NULL(&tmp); - offset = &tmp; + ZVAL_NULL(&tmp_offset); } else { - SEPARATE_ARG_IF_REF(offset); + ZVAL_DEREF(offset); + ZVAL_COPY(&tmp_offset, offset); } - zend_call_method_with_2_params(object, ce, NULL, "offsetset", NULL, offset, value); - zval_ptr_dtor(offset); + ZVAL_COPY(&tmp_object, object); + zend_call_method_with_2_params(&tmp_object, ce, NULL, "offsetset", NULL, &tmp_offset, value); + zval_ptr_dtor(&tmp_object); + zval_ptr_dtor(&tmp_offset); } else { zend_throw_error(NULL, "Cannot use object of type %s as array", ZSTR_VAL(ce->name)); } @@ -800,17 +806,19 @@ static void zend_std_write_dimension(zval *object, zval *offset, zval *value) /* static int zend_std_has_dimension(zval *object, zval *offset, int check_empty) /* {{{ */ { zend_class_entry *ce = Z_OBJCE_P(object); - zval retval; + zval retval, tmp_offset, tmp_object; int result; if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) { - SEPARATE_ARG_IF_REF(offset); - zend_call_method_with_1_params(object, ce, NULL, "offsetexists", &retval, offset); + ZVAL_DEREF(offset); + ZVAL_COPY(&tmp_offset, offset); + ZVAL_COPY(&tmp_object, object); + zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetexists", &retval, &tmp_offset); if (EXPECTED(Z_TYPE(retval) != IS_UNDEF)) { result = i_zend_is_true(&retval); zval_ptr_dtor(&retval); if (check_empty && result && EXPECTED(!EG(exception))) { - zend_call_method_with_1_params(object, ce, NULL, "offsetget", &retval, offset); + zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetget", &retval, &tmp_offset); if (EXPECTED(Z_TYPE(retval) != IS_UNDEF)) { result = i_zend_is_true(&retval); zval_ptr_dtor(&retval); @@ -819,7 +827,8 @@ static int zend_std_has_dimension(zval *object, zval *offset, int check_empty) / } else { result = 0; } - zval_ptr_dtor(offset); + zval_ptr_dtor(&tmp_object); + zval_ptr_dtor(&tmp_offset); } else { zend_throw_error(NULL, "Cannot use object of type %s as array", ZSTR_VAL(ce->name)); return 0; @@ -981,11 +990,15 @@ exit: static void zend_std_unset_dimension(zval *object, zval *offset) /* {{{ */ { zend_class_entry *ce = Z_OBJCE_P(object); + zval tmp_offset, tmp_object; if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1)) { - SEPARATE_ARG_IF_REF(offset); - zend_call_method_with_1_params(object, ce, NULL, "offsetunset", NULL, offset); - zval_ptr_dtor(offset); + ZVAL_DEREF(offset); + ZVAL_COPY(&tmp_offset, offset); + ZVAL_COPY(&tmp_object, object); + zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetunset", NULL, &tmp_offset); + zval_ptr_dtor(&tmp_object); + zval_ptr_dtor(&tmp_offset); } else { zend_throw_error(NULL, "Cannot use object of type %s as array", ZSTR_VAL(ce->name)); } |