Skip to content

Commit

Permalink
Fix OSS-fuzz #60709 unseting op via globals
Browse files Browse the repository at this point in the history
It turns out not just NULL is affected nor -- but also on booleans and this also affects properties
  • Loading branch information
Girgias committed Aug 1, 2023
1 parent 8874384 commit 6ae9cf4
Show file tree
Hide file tree
Showing 4 changed files with 333 additions and 3 deletions.
36 changes: 36 additions & 0 deletions Zend/tests/in-de-crement/oss-fuzz-60709_globals.phpt
@@ -0,0 +1,36 @@
--TEST--
oss-fuzz #60709: Test
--FILE--
<?php
set_error_handler(function($_, $m) {
echo "$m\n";
unset($GLOBALS['x']);
});

echo "POST DEC\n";
var_dump($x--);
unset($x);
echo "POST INC\n";
var_dump($x++);
unset($x);
echo "PRE DEC\n";
var_dump(--$x);
unset($x);
echo "PRE INC\n";
var_dump(++$x);
?>
--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)
130 changes: 130 additions & 0 deletions 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--
<?php
set_error_handler(function($_, $m) {
echo "$m\n";
unset($GLOBALS['x']);
});
echo "NULL (only --)\n";
echo "POST DEC\n";
$x = null;
var_dump($x--);
unset($x);
echo "PRE DEC\n";
$x = null;
var_dump(--$x);
unset($x);
echo "Empty string\n";
echo "POST INC\n";
$x = "";
var_dump($x++);
unset($x);
echo "POST DEC\n";
$x = "";
var_dump($x--);
unset($x);
echo "PRE INC\n";
$x = "";
var_dump(++$x);
unset($x);
echo "PRE DEC\n";
$x = "";
var_dump(--$x);
unset($x);
echo "Non fill ASCII (only ++)\n";
echo "POST INC\n";
$x = " ad ";
var_dump($x++);
unset($x);
echo "PRE INC\n";
$x = " ad ";
var_dump(++$x);
unset($x);
echo "Bool\n";
echo "POST INC\n";
$x = false;
var_dump($x++);
unset($x);
echo "POST DEC\n";
$x = false;
var_dump($x--);
unset($x);
echo "PRE INC\n";
$x = false;
var_dump(++$x);
unset($x);
echo "PRE DEC\n";
$x = false;
var_dump(--$x);
unset($x);
echo "POST INC\n";
$x = true;
var_dump($x++);
unset($x);
echo "POST DEC\n";
$x = true;
var_dump($x--);
unset($x);
echo "PRE INC\n";
$x = true;
var_dump(++$x);
unset($x);
echo "PRE DEC\n";
$x = true;
var_dump(--$x);
unset($x);
?>
--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)
143 changes: 143 additions & 0 deletions Zend/tests/in-de-crement/unset_object_property_in_error_handler.phpt
@@ -0,0 +1,143 @@
--TEST--
Unset property via error_handler
--FILE--
<?php
class C {
public $a;

public function errorHandler($errno, $errstr) {
var_dump($errstr);
unset($this->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)
27 changes: 24 additions & 3 deletions Zend/zend_operators.c
Expand Up @@ -2657,9 +2657,18 @@ ZEND_API zend_result ZEND_FASTCALL increment_function(zval *op1) /* {{{ */
}
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(&copy, 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, &copy);
if (EG(exception)) {
return FAILURE;
}
break;
}
case IS_REFERENCE:
op1 = Z_REFVAL_P(op1);
goto try_again;
Expand Down Expand Up @@ -2735,19 +2744,31 @@ ZEND_API zend_result ZEND_FASTCALL decrement_function(zval *op1) /* {{{ */
}
}
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(&copy, 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, &copy);
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(&copy, 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, &copy);
if (EG(exception)) {
return FAILURE;
}
break;
}
case IS_REFERENCE:
op1 = Z_REFVAL_P(op1);
goto try_again;
Expand Down

0 comments on commit 6ae9cf4

Please sign in to comment.