Skip to content

Commit 44b1ac3

Browse files
committed
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
1 parent 54277ee commit 44b1ac3

File tree

6 files changed

+367
-0
lines changed

6 files changed

+367
-0
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
oss-fuzz #60709: Test
3+
--FILE--
4+
<?php
5+
set_error_handler(function($_, $m) {
6+
echo "$m\n";
7+
unset($GLOBALS['x']);
8+
});
9+
10+
echo "POST DEC\n";
11+
var_dump($x--);
12+
unset($x);
13+
echo "POST INC\n";
14+
var_dump($x++);
15+
unset($x);
16+
echo "PRE DEC\n";
17+
var_dump(--$x);
18+
unset($x);
19+
echo "PRE INC\n";
20+
var_dump(++$x);
21+
?>
22+
--EXPECT--
23+
POST DEC
24+
Undefined variable $x
25+
Decrement on type null has no effect, this will change in the next major version of PHP
26+
NULL
27+
POST INC
28+
Undefined variable $x
29+
NULL
30+
PRE DEC
31+
Undefined variable $x
32+
Decrement on type null has no effect, this will change in the next major version of PHP
33+
Undefined variable $x
34+
NULL
35+
PRE INC
36+
Undefined variable $x
37+
int(1)
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
--TEST--
2+
Unset variable via $GLOBALS array in error_handler
3+
--FILE--
4+
<?php
5+
set_error_handler(function($_, $m) {
6+
echo "$m\n";
7+
unset($GLOBALS['x']);
8+
});
9+
echo "NULL (only --)\n";
10+
echo "POST DEC\n";
11+
$x = null;
12+
var_dump($x--);
13+
unset($x);
14+
echo "PRE DEC\n";
15+
$x = null;
16+
var_dump(--$x);
17+
unset($x);
18+
echo "Empty string\n";
19+
echo "POST INC\n";
20+
$x = "";
21+
var_dump($x++);
22+
unset($x);
23+
echo "POST DEC\n";
24+
$x = "";
25+
var_dump($x--);
26+
unset($x);
27+
echo "PRE INC\n";
28+
$x = "";
29+
var_dump(++$x);
30+
unset($x);
31+
echo "PRE DEC\n";
32+
$x = "";
33+
var_dump(--$x);
34+
unset($x);
35+
echo "Non fill ASCII (only ++)\n";
36+
echo "POST INC\n";
37+
$x = " ad ";
38+
var_dump($x++);
39+
unset($x);
40+
echo "PRE INC\n";
41+
$x = " ad ";
42+
var_dump(++$x);
43+
unset($x);
44+
echo "Bool\n";
45+
echo "POST INC\n";
46+
$x = false;
47+
var_dump($x++);
48+
unset($x);
49+
echo "POST DEC\n";
50+
$x = false;
51+
var_dump($x--);
52+
unset($x);
53+
echo "PRE INC\n";
54+
$x = false;
55+
var_dump(++$x);
56+
unset($x);
57+
echo "PRE DEC\n";
58+
$x = false;
59+
var_dump(--$x);
60+
unset($x);
61+
echo "POST INC\n";
62+
$x = true;
63+
var_dump($x++);
64+
unset($x);
65+
echo "POST DEC\n";
66+
$x = true;
67+
var_dump($x--);
68+
unset($x);
69+
echo "PRE INC\n";
70+
$x = true;
71+
var_dump(++$x);
72+
unset($x);
73+
echo "PRE DEC\n";
74+
$x = true;
75+
var_dump(--$x);
76+
unset($x);
77+
?>
78+
--EXPECT--
79+
NULL (only --)
80+
POST DEC
81+
Decrement on type null has no effect, this will change in the next major version of PHP
82+
NULL
83+
PRE DEC
84+
Decrement on type null has no effect, this will change in the next major version of PHP
85+
Undefined variable $x
86+
NULL
87+
Empty string
88+
POST INC
89+
Increment on non-alphanumeric string is deprecated
90+
string(0) ""
91+
POST DEC
92+
Decrement on empty string is deprecated as non-numeric
93+
string(0) ""
94+
PRE INC
95+
Increment on non-alphanumeric string is deprecated
96+
string(1) "1"
97+
PRE DEC
98+
Decrement on empty string is deprecated as non-numeric
99+
int(-1)
100+
Non fill ASCII (only ++)
101+
POST INC
102+
Increment on non-alphanumeric string is deprecated
103+
string(4) " ad "
104+
PRE INC
105+
Increment on non-alphanumeric string is deprecated
106+
string(4) " ad "
107+
Bool
108+
POST INC
109+
Increment on type bool has no effect, this will change in the next major version of PHP
110+
bool(false)
111+
POST DEC
112+
Decrement on type bool has no effect, this will change in the next major version of PHP
113+
bool(false)
114+
PRE INC
115+
Increment on type bool has no effect, this will change in the next major version of PHP
116+
Undefined variable $x
117+
NULL
118+
PRE DEC
119+
Decrement on type bool has no effect, this will change in the next major version of PHP
120+
Undefined variable $x
121+
NULL
122+
POST INC
123+
Increment on type bool has no effect, this will change in the next major version of PHP
124+
bool(true)
125+
POST DEC
126+
Decrement on type bool has no effect, this will change in the next major version of PHP
127+
bool(true)
128+
PRE INC
129+
Increment on type bool has no effect, this will change in the next major version of PHP
130+
Undefined variable $x
131+
NULL
132+
PRE DEC
133+
Decrement on type bool has no effect, this will change in the next major version of PHP
134+
Undefined variable $x
135+
NULL
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
--TEST--
2+
Unset property via error_handler
3+
--FILE--
4+
<?php
5+
class C {
6+
public $a;
7+
8+
public function errorHandler($errno, $errstr) {
9+
var_dump($errstr);
10+
unset($this->a);
11+
}
12+
}
13+
14+
$c = new C;
15+
set_error_handler([$c, 'errorHandler']);
16+
17+
/* default property value */
18+
var_dump(--$c->a);
19+
20+
echo "NULL (only --)\n";
21+
echo "POST DEC\n";
22+
$c->a = null;
23+
var_dump($c->a--);
24+
unset($c->a);
25+
echo "PRE DEC\n";
26+
$c->a = null;
27+
var_dump(--$c->a);
28+
unset($c->a);
29+
echo "Empty string\n";
30+
echo "POST INC\n";
31+
$c->a = "";
32+
var_dump($c->a++);
33+
unset($c->a);
34+
echo "POST DEC\n";
35+
$c->a = "";
36+
var_dump($c->a--);
37+
unset($c->a);
38+
echo "PRE INC\n";
39+
$c->a = "";
40+
var_dump(++$c->a);
41+
unset($c->a);
42+
echo "PRE DEC\n";
43+
$c->a = "";
44+
var_dump(--$c->a);
45+
unset($c->a);
46+
echo "Non fill ASCII (only ++)\n";
47+
echo "POST INC\n";
48+
$c->a = " ad ";
49+
var_dump($c->a++);
50+
unset($c->a);
51+
echo "PRE INC\n";
52+
$c->a = " ad ";
53+
var_dump(++$c->a);
54+
unset($c->a);
55+
echo "Bool\n";
56+
echo "POST INC\n";
57+
$c->a = false;
58+
var_dump($c->a++);
59+
unset($c->a);
60+
echo "POST DEC\n";
61+
$c->a = false;
62+
var_dump($c->a--);
63+
unset($c->a);
64+
echo "PRE INC\n";
65+
$c->a = false;
66+
var_dump(++$c->a);
67+
unset($c->a);
68+
echo "PRE DEC\n";
69+
$c->a = false;
70+
var_dump(--$c->a);
71+
unset($c->a);
72+
echo "POST INC\n";
73+
$c->a = true;
74+
var_dump($c->a++);
75+
unset($c->a);
76+
echo "POST DEC\n";
77+
$c->a = true;
78+
var_dump($c->a--);
79+
unset($c->a);
80+
echo "PRE INC\n";
81+
$c->a = true;
82+
var_dump(++$c->a);
83+
unset($c->a);
84+
echo "PRE DEC\n";
85+
$c->a = true;
86+
var_dump(--$c->a);
87+
unset($c->a);
88+
?>
89+
--EXPECT--
90+
string(87) "Decrement on type null has no effect, this will change in the next major version of PHP"
91+
NULL
92+
NULL (only --)
93+
POST DEC
94+
string(87) "Decrement on type null has no effect, this will change in the next major version of PHP"
95+
NULL
96+
PRE DEC
97+
string(87) "Decrement on type null has no effect, this will change in the next major version of PHP"
98+
NULL
99+
Empty string
100+
POST INC
101+
string(50) "Increment on non-alphanumeric string is deprecated"
102+
string(0) ""
103+
POST DEC
104+
string(54) "Decrement on empty string is deprecated as non-numeric"
105+
string(0) ""
106+
PRE INC
107+
string(50) "Increment on non-alphanumeric string is deprecated"
108+
string(1) "1"
109+
PRE DEC
110+
string(54) "Decrement on empty string is deprecated as non-numeric"
111+
int(-1)
112+
Non fill ASCII (only ++)
113+
POST INC
114+
string(50) "Increment on non-alphanumeric string is deprecated"
115+
string(4) " ad "
116+
PRE INC
117+
string(50) "Increment on non-alphanumeric string is deprecated"
118+
string(4) " ad "
119+
Bool
120+
POST INC
121+
string(87) "Increment on type bool has no effect, this will change in the next major version of PHP"
122+
bool(false)
123+
POST DEC
124+
string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP"
125+
bool(false)
126+
PRE INC
127+
string(87) "Increment on type bool has no effect, this will change in the next major version of PHP"
128+
NULL
129+
PRE DEC
130+
string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP"
131+
NULL
132+
POST INC
133+
string(87) "Increment on type bool has no effect, this will change in the next major version of PHP"
134+
bool(true)
135+
POST DEC
136+
string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP"
137+
bool(true)
138+
PRE INC
139+
string(87) "Increment on type bool has no effect, this will change in the next major version of PHP"
140+
NULL
141+
PRE DEC
142+
string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP"
143+
NULL

Zend/zend_execute.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,6 +2022,10 @@ static void zend_pre_incdec_property_zval(zval *prop, zend_property_info *prop_i
20222022
} while (0);
20232023
}
20242024
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2025+
/* Error handler can mess up properties and unset it */
2026+
if (UNEXPECTED(Z_TYPE_P(prop) == IS_UNDEF)) {
2027+
ZVAL_NULL(prop);
2028+
}
20252029
ZVAL_COPY(EX_VAR(opline->result.var), prop);
20262030
}
20272031
}

Zend/zend_vm_def.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,6 +1509,14 @@ ZEND_VM_HELPER(zend_pre_inc_helper, VAR|CV, ANY)
15091509
} while (0);
15101510

15111511
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1512+
/* Error handler can mess up globals and unset it */
1513+
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
1514+
ZVAL_UNDEFINED_OP1();
1515+
if (UNEXPECTED(EG(exception))) {
1516+
HANDLE_EXCEPTION();
1517+
}
1518+
ZVAL_NULL(var_ptr);
1519+
}
15121520
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
15131521
}
15141522

@@ -1567,6 +1575,14 @@ ZEND_VM_HELPER(zend_pre_dec_helper, VAR|CV, ANY)
15671575
} while (0);
15681576

15691577
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1578+
/* Error handler can mess up globals and unset it */
1579+
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
1580+
ZVAL_UNDEFINED_OP1();
1581+
if (UNEXPECTED(EG(exception))) {
1582+
HANDLE_EXCEPTION();
1583+
}
1584+
ZVAL_NULL(var_ptr);
1585+
}
15701586
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
15711587
}
15721588

0 commit comments

Comments
 (0)