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
This commit is contained in:
George Peter Banyard 2023-07-21 18:08:58 +01:00
parent 8874384921
commit 6ae9cf40d1
4 changed files with 333 additions and 3 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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(&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;
@ -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(&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;