Skip to content

Commit 8fb3ef6

Browse files
committed
Merge branch 'PHP-7.4'
* PHP-7.4: Fixed bug #78937 (Preloading unlinkable anonymous class can segfault)
2 parents 764c815 + 20ef51d commit 8fb3ef6

File tree

10 files changed

+162
-2
lines changed

10 files changed

+162
-2
lines changed

Zend/zend_compile.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,8 +1104,12 @@ ZEND_API int do_bind_class(zval *lcname, zend_string *lc_parent_name) /* {{{ */
11041104

11051105
if (UNEXPECTED(!zv)) {
11061106
ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname));
1107-
ZEND_ASSERT(ce && "Class with lcname should be registered");
1108-
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
1107+
if (ce) {
1108+
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
1109+
} else {
1110+
ZEND_ASSERT(EG(current_execute_data)->func->op_array.fn_flags & ZEND_ACC_PRELOADED);
1111+
zend_error_noreturn(E_ERROR, "Class %s wasn't preloaded", Z_STRVAL_P(lcname));
1112+
}
11091113
return FAILURE;
11101114
}
11111115

Zend/zend_vm_def.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7108,6 +7108,11 @@ ZEND_VM_HANDLER(146, ZEND_DECLARE_ANON_CLASS, ANY, ANY, CACHE_SLOT)
71087108
if (UNEXPECTED(ce == NULL)) {
71097109
zend_string *rtd_key = Z_STR_P(RT_CONSTANT(opline, opline->op1));
71107110
zv = zend_hash_find_ex(EG(class_table), rtd_key, 1);
7111+
if (UNEXPECTED(zv == NULL)) {
7112+
SAVE_OPLINE();
7113+
ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_PRELOADED);
7114+
zend_error_noreturn(E_ERROR, "Anonymous class wasn't preloaded");
7115+
}
71117116
ZEND_ASSERT(zv != NULL);
71127117
ce = Z_CE_P(zv);
71137118
if (!(ce->ce_flags & ZEND_ACC_LINKED)) {

Zend/zend_vm_execute.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2361,6 +2361,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_CLASS_SPEC_HANDLE
23612361
if (UNEXPECTED(ce == NULL)) {
23622362
zend_string *rtd_key = Z_STR_P(RT_CONSTANT(opline, opline->op1));
23632363
zv = zend_hash_find_ex(EG(class_table), rtd_key, 1);
2364+
if (UNEXPECTED(zv == NULL)) {
2365+
SAVE_OPLINE();
2366+
ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_PRELOADED);
2367+
zend_error_noreturn(E_ERROR, "Anonymous class wasn't preloaded");
2368+
}
23642369
ZEND_ASSERT(zv != NULL);
23652370
ce = Z_CE_P(zv);
23662371
if (!(ce->ce_flags & ZEND_ACC_LINKED)) {

ext/opcache/tests/bug78937_1.phpt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Bug #78937.1 (Preloading unlinkable anonymous class can segfault)
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
opcache.preload={PWD}/preload_bug78937.inc
8+
--SKIPIF--
9+
<?php require_once('skipif.inc'); ?>
10+
--FILE--
11+
<?php
12+
class Bar {
13+
}
14+
var_dump(foo());
15+
?>
16+
--EXPECTF--
17+
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
18+
19+
Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
20+
21+
Fatal error: Anonymous class wasn't preloaded in %spreload_bug78937.inc on line 3
22+

ext/opcache/tests/bug78937_2.phpt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Bug #78937.2 (Preloading unlinkable anonymous class can segfault)
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
opcache.preload={PWD}/preload_bug78937.inc
8+
--SKIPIF--
9+
<?php require_once('skipif.inc'); ?>
10+
--FILE--
11+
<?php
12+
include(__DIR__ . "/preload_bug78937.inc");
13+
class Bar {
14+
}
15+
var_dump(foo());
16+
?>
17+
--EXPECTF--
18+
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
19+
20+
Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
21+
object(class@anonymous)#%d (0) {
22+
}

ext/opcache/tests/bug78937_3.phpt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
Bug #78937.3 (Preloading unlinkable anonymous class can segfault)
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
opcache.preload={PWD}/preload_bug78937.inc
8+
--SKIPIF--
9+
<?php require_once('skipif.inc'); ?>
10+
--FILE--
11+
<?php
12+
include(__DIR__ . "/preload_bug78937.inc");
13+
var_dump(foo());
14+
?>
15+
--EXPECTF--
16+
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
17+
18+
Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
19+
20+
Fatal error: Uncaught Error: Class 'Bar' not found in %spreload_bug78937.inc:3
21+
Stack trace:
22+
#0 %sbug78937_3.php(3): foo()
23+
#1 {main}
24+
thrown in %spreload_bug78937.inc on line 3

ext/opcache/tests/bug78937_4.phpt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Bug #78937.4 (Preloading unlinkable anonymous class can segfault)
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
opcache.preload={PWD}/preload_bug78937.inc
8+
--SKIPIF--
9+
<?php require_once('skipif.inc'); ?>
10+
--FILE--
11+
<?php
12+
class Bar {
13+
}
14+
bar();
15+
var_dump(new Foo);
16+
?>
17+
--EXPECTF--
18+
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
19+
20+
Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
21+
22+
Fatal error: Class foo wasn't preloaded in %spreload_bug78937.inc on line 6

ext/opcache/tests/bug78937_5.phpt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
Bug #78937.5 (Preloading unlinkable anonymous class can segfault)
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
opcache.preload={PWD}/preload_bug78937.inc
8+
--SKIPIF--
9+
<?php require_once('skipif.inc'); ?>
10+
--FILE--
11+
<?php
12+
include(__DIR__ . "/preload_bug78937.inc");
13+
class Bar {
14+
}
15+
bar();
16+
var_dump(new Foo);
17+
?>
18+
--EXPECTF--
19+
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
20+
21+
Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
22+
object(Foo)#%d (0) {
23+
}

ext/opcache/tests/bug78937_6.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Bug #78937.6 (Preloading unlinkable anonymous class can segfault)
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
opcache.preload={PWD}/preload_bug78937.inc
8+
--SKIPIF--
9+
<?php require_once('skipif.inc'); ?>
10+
--FILE--
11+
<?php
12+
include(__DIR__ . "/preload_bug78937.inc");
13+
bar();
14+
var_dump(new Foo);
15+
?>
16+
--EXPECTF--
17+
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
18+
19+
Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
20+
21+
Fatal error: Uncaught Error: Class 'Bar' not found in %spreload_bug78937.inc:6
22+
Stack trace:
23+
#0 %sbug78937_6.php(3): bar()
24+
#1 {main}
25+
thrown in %spreload_bug78937.inc on line 6
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
function foo() {
3+
return new class extends Bar {};
4+
}
5+
function bar() {
6+
class Foo extends Bar {
7+
}
8+
}

0 commit comments

Comments
 (0)