summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/tests/bug75420.10.phpt21
-rw-r--r--Zend/tests/bug75420.11.phpt20
-rw-r--r--Zend/tests/bug75420.12.phpt21
-rw-r--r--Zend/tests/bug75420.13.phpt20
-rw-r--r--Zend/tests/bug75420.14.phpt20
-rw-r--r--Zend/tests/bug75420.15.phpt20
-rw-r--r--Zend/tests/bug75420.16.phpt20
-rw-r--r--Zend/tests/bug75420.9.phpt20
-rw-r--r--Zend/zend_object_handlers.c59
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));
}