diff options
author | Dmitry Stogov <dmitry@zend.com> | 2017-10-26 16:04:20 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2017-10-26 16:04:20 +0300 |
commit | 503df277abbce518a65270c715b7f52fd021230c (patch) | |
tree | 05d06e115521c2eefd02dca246094c4648f2d51c /Zend | |
parent | d3146889ab00e202a8b2669d25dda614492318ec (diff) | |
parent | 98eee90734c4fabf3f3a3d4168576cb6b25ad9b1 (diff) | |
download | php-git-503df277abbce518a65270c715b7f52fd021230c.tar.gz |
Merge branch 'PHP-7.0' into PHP-7.1
* PHP-7.0:
Fixed indirect modification of magic ArrayAccess method arguments
Diffstat (limited to 'Zend')
-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 e8530340fb..10045b53f1 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -790,34 +790,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))) { @@ -836,17 +840,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)); } @@ -856,17 +862,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); @@ -875,7 +883,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; @@ -1032,11 +1041,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)); } |