From 6ae9cf40d11eb31562246fbcac7cc73cdc8a2278 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Fri, 21 Jul 2023 18:08:58 +0100 Subject: [PATCH] Fix OSS-fuzz #60709 unseting op via globals It turns out not just NULL is affected nor -- but also on booleans and this also affects properties --- .../in-de-crement/oss-fuzz-60709_globals.phpt | 36 +++++ .../unset_globals_in_error_handler.phpt | 130 ++++++++++++++++ ...nset_object_property_in_error_handler.phpt | 143 ++++++++++++++++++ Zend/zend_operators.c | 27 +++- 4 files changed, 333 insertions(+), 3 deletions(-) create mode 100644 Zend/tests/in-de-crement/oss-fuzz-60709_globals.phpt create mode 100644 Zend/tests/in-de-crement/unset_globals_in_error_handler.phpt create mode 100644 Zend/tests/in-de-crement/unset_object_property_in_error_handler.phpt diff --git a/Zend/tests/in-de-crement/oss-fuzz-60709_globals.phpt b/Zend/tests/in-de-crement/oss-fuzz-60709_globals.phpt new file mode 100644 index 00000000000..d6405a28f96 --- /dev/null +++ b/Zend/tests/in-de-crement/oss-fuzz-60709_globals.phpt @@ -0,0 +1,36 @@ +--TEST-- +oss-fuzz #60709: Test +--FILE-- + +--EXPECT-- +POST DEC +Undefined variable $x +Decrement on type null has no effect, this will change in the next major version of PHP +NULL +POST INC +Undefined variable $x +NULL +PRE DEC +Undefined variable $x +Decrement on type null has no effect, this will change in the next major version of PHP +NULL +PRE INC +Undefined variable $x +int(1) diff --git a/Zend/tests/in-de-crement/unset_globals_in_error_handler.phpt b/Zend/tests/in-de-crement/unset_globals_in_error_handler.phpt new file mode 100644 index 00000000000..d2f27ed3232 --- /dev/null +++ b/Zend/tests/in-de-crement/unset_globals_in_error_handler.phpt @@ -0,0 +1,130 @@ +--TEST-- +Unset variable via $GLOBALS array in error_handler +--FILE-- + +--EXPECT-- +NULL (only --) +POST DEC +Decrement on type null has no effect, this will change in the next major version of PHP +NULL +PRE DEC +Decrement on type null has no effect, this will change in the next major version of PHP +NULL +Empty string +POST INC +Increment on non-alphanumeric string is deprecated +string(0) "" +POST DEC +Decrement on empty string is deprecated as non-numeric +string(0) "" +PRE INC +Increment on non-alphanumeric string is deprecated +string(1) "1" +PRE DEC +Decrement on empty string is deprecated as non-numeric +int(-1) +Non fill ASCII (only ++) +POST INC +Increment on non-alphanumeric string is deprecated +string(4) " ad " +PRE INC +Increment on non-alphanumeric string is deprecated +string(4) " ad " +Bool +POST INC +Increment on type bool has no effect, this will change in the next major version of PHP +bool(false) +POST DEC +Decrement on type bool has no effect, this will change in the next major version of PHP +bool(false) +PRE INC +Increment on type bool has no effect, this will change in the next major version of PHP +bool(false) +PRE DEC +Decrement on type bool has no effect, this will change in the next major version of PHP +bool(false) +POST INC +Increment on type bool has no effect, this will change in the next major version of PHP +bool(true) +POST DEC +Decrement on type bool has no effect, this will change in the next major version of PHP +bool(true) +PRE INC +Increment on type bool has no effect, this will change in the next major version of PHP +bool(true) +PRE DEC +Decrement on type bool has no effect, this will change in the next major version of PHP +bool(true) diff --git a/Zend/tests/in-de-crement/unset_object_property_in_error_handler.phpt b/Zend/tests/in-de-crement/unset_object_property_in_error_handler.phpt new file mode 100644 index 00000000000..33d18b9a627 --- /dev/null +++ b/Zend/tests/in-de-crement/unset_object_property_in_error_handler.phpt @@ -0,0 +1,143 @@ +--TEST-- +Unset property via error_handler +--FILE-- +a); + } +} + +$c = new C; +set_error_handler([$c, 'errorHandler']); + +/* default property value */ +var_dump(--$c->a); + +echo "NULL (only --)\n"; +echo "POST DEC\n"; +$c->a = null; +var_dump($c->a--); +unset($c->a); +echo "PRE DEC\n"; +$c->a = null; +var_dump(--$c->a); +unset($c->a); +echo "Empty string\n"; +echo "POST INC\n"; +$c->a = ""; +var_dump($c->a++); +unset($c->a); +echo "POST DEC\n"; +$c->a = ""; +var_dump($c->a--); +unset($c->a); +echo "PRE INC\n"; +$c->a = ""; +var_dump(++$c->a); +unset($c->a); +echo "PRE DEC\n"; +$c->a = ""; +var_dump(--$c->a); +unset($c->a); +echo "Non fill ASCII (only ++)\n"; +echo "POST INC\n"; +$c->a = " ad "; +var_dump($c->a++); +unset($c->a); +echo "PRE INC\n"; +$c->a = " ad "; +var_dump(++$c->a); +unset($c->a); +echo "Bool\n"; +echo "POST INC\n"; +$c->a = false; +var_dump($c->a++); +unset($c->a); +echo "POST DEC\n"; +$c->a = false; +var_dump($c->a--); +unset($c->a); +echo "PRE INC\n"; +$c->a = false; +var_dump(++$c->a); +unset($c->a); +echo "PRE DEC\n"; +$c->a = false; +var_dump(--$c->a); +unset($c->a); +echo "POST INC\n"; +$c->a = true; +var_dump($c->a++); +unset($c->a); +echo "POST DEC\n"; +$c->a = true; +var_dump($c->a--); +unset($c->a); +echo "PRE INC\n"; +$c->a = true; +var_dump(++$c->a); +unset($c->a); +echo "PRE DEC\n"; +$c->a = true; +var_dump(--$c->a); +unset($c->a); +?> +--EXPECT-- +string(87) "Decrement on type null has no effect, this will change in the next major version of PHP" +NULL +NULL (only --) +POST DEC +string(87) "Decrement on type null has no effect, this will change in the next major version of PHP" +NULL +PRE DEC +string(87) "Decrement on type null has no effect, this will change in the next major version of PHP" +NULL +Empty string +POST INC +string(50) "Increment on non-alphanumeric string is deprecated" +string(0) "" +POST DEC +string(54) "Decrement on empty string is deprecated as non-numeric" +string(0) "" +PRE INC +string(50) "Increment on non-alphanumeric string is deprecated" +string(1) "1" +PRE DEC +string(54) "Decrement on empty string is deprecated as non-numeric" +int(-1) +Non fill ASCII (only ++) +POST INC +string(50) "Increment on non-alphanumeric string is deprecated" +string(4) " ad " +PRE INC +string(50) "Increment on non-alphanumeric string is deprecated" +string(4) " ad " +Bool +POST INC +string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" +bool(false) +POST DEC +string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" +bool(false) +PRE INC +string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" +bool(false) +PRE DEC +string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" +bool(false) +POST INC +string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" +bool(true) +POST DEC +string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" +bool(true) +PRE INC +string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" +bool(true) +PRE DEC +string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" +bool(true) diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 293d7cc029e..7f1b3234ace 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2657,9 +2657,18 @@ try_again: } break; case IS_FALSE: - case IS_TRUE: + case IS_TRUE: { + /* Error handler can undef/change type of op1, save it and reset it in case those cases */ + zval copy; + ZVAL_COPY_VALUE(©, op1); zend_error(E_WARNING, "Increment on type bool has no effect, this will change in the next major version of PHP"); + zval_ptr_dtor(op1); + ZVAL_COPY_VALUE(op1, ©); + if (EG(exception)) { + return FAILURE; + } break; + } case IS_REFERENCE: op1 = Z_REFVAL_P(op1); goto try_again; @@ -2735,19 +2744,31 @@ try_again: } } break; - case IS_NULL: + case IS_NULL: { + /* Error handler can undef/change type of op1, save it and reset it in case those cases */ + zval copy; + ZVAL_COPY_VALUE(©, op1); zend_error(E_WARNING, "Decrement on type null has no effect, this will change in the next major version of PHP"); + zval_ptr_dtor(op1); + ZVAL_COPY_VALUE(op1, ©); if (EG(exception)) { return FAILURE; } break; + } case IS_FALSE: - case IS_TRUE: + case IS_TRUE: { + /* Error handler can undef/change type of op1, save it and reset it in case those cases */ + zval copy; + ZVAL_COPY_VALUE(©, op1); zend_error(E_WARNING, "Decrement on type bool has no effect, this will change in the next major version of PHP"); + zval_ptr_dtor(op1); + ZVAL_COPY_VALUE(op1, ©); if (EG(exception)) { return FAILURE; } break; + } case IS_REFERENCE: op1 = Z_REFVAL_P(op1); goto try_again;