Skip to content

Commit 1548418

Browse files
committed
Fix may_throw for ASSIGN_OBJ
The code did not account for a number of possible exceptions.
1 parent f55d78e commit 1548418

File tree

2 files changed

+62
-18
lines changed

2 files changed

+62
-18
lines changed

ext/opcache/Optimizer/zend_inference.c

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4572,7 +4572,7 @@ int zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op, const ze
45724572
return (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_TRUE|MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE)) || opline->op2_type == IS_UNUSED ||
45734573
(t2 & (MAY_BE_UNDEF|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
45744574
case ZEND_ASSIGN_OBJ:
4575-
if (t1 & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_OBJECT))) {
4575+
if (t1 & (MAY_BE_ANY-MAY_BE_OBJECT)) {
45764576
return 1;
45774577
}
45784578
if ((opline+1)->op1_type == IS_CV) {
@@ -4589,24 +4589,21 @@ int zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op, const ze
45894589
return 1;
45904590
}
45914591

4592-
if (op_array->scope != ce && ce->default_properties_count) {
4593-
zend_property_info *prop_info;
4592+
if (opline->op2_type != IS_CONST) {
4593+
return 1;
4594+
}
45944595

4595-
if (opline->op2_type == IS_CONST) {
4596-
prop_info = zend_hash_find_ptr(&ce->properties_info,
4597-
Z_STR_P(CRT_CONSTANT(opline->op2)));
4598-
if (prop_info && !(prop_info->flags & ZEND_ACC_PUBLIC)) {
4599-
return 1;
4600-
}
4601-
} else {
4602-
if (t2 & (MAY_BE_ANY-MAY_BE_STRING)) {
4603-
return 1;
4604-
}
4605-
ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
4606-
if (!(prop_info->flags & ZEND_ACC_PUBLIC)) {
4607-
return 1;
4608-
}
4609-
} ZEND_HASH_FOREACH_END();
4596+
zend_string *prop_name = Z_STR_P(CRT_CONSTANT(opline->op2));
4597+
if (ZSTR_LEN(prop_name) > 0 && ZSTR_VAL(prop_name)[0] == '\0') {
4598+
return 1;
4599+
}
4600+
4601+
if (op_array->scope != ce && ce->default_properties_count) {
4602+
zend_property_info *prop_info =
4603+
zend_hash_find_ptr(&ce->properties_info, prop_name);
4604+
if (prop_info && (!(prop_info->flags & ZEND_ACC_PUBLIC)
4605+
|| ZEND_TYPE_IS_SET(prop_info->type))) {
4606+
return 1;
46104607
}
46114608
}
46124609
return 0;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
--TEST--
2+
Make sure various ASSIGN_OBJ exceptions are not optimized away
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
public stdClass $x;
8+
}
9+
10+
function test_invalid_prop_type() {
11+
$test = new Test;
12+
$test->x = "";
13+
}
14+
function test_invalid_prop_name(string $name) {
15+
$test = new stdClass;
16+
$test->$name = null;
17+
}
18+
function test_invalid_obj_type($c) {
19+
if ($c) {
20+
$test = new stdClass;
21+
} else {
22+
$test = null;
23+
}
24+
$test->x = "";
25+
}
26+
27+
try {
28+
test_invalid_prop_type();
29+
} catch (TypeError $e) {
30+
echo $e->getMessage(), "\n";
31+
}
32+
try {
33+
test_invalid_prop_name("\0");
34+
} catch (Error $e) {
35+
echo $e->getMessage(), "\n";
36+
}
37+
try {
38+
test_invalid_obj_type(false);
39+
} catch (Error $e) {
40+
echo $e->getMessage(), "\n";
41+
}
42+
43+
?>
44+
--EXPECT--
45+
Cannot assign string to property Test::$x of type stdClass
46+
Cannot access property starting with "\0"
47+
Attempt to assign property "x" on null

0 commit comments

Comments
 (0)