diff options
-rw-r--r-- | Zend/zend_compile.c | 8 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 5 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 5 | ||||
-rw-r--r-- | ext/opcache/tests/bug78937_1.phpt | 22 | ||||
-rw-r--r-- | ext/opcache/tests/bug78937_2.phpt | 22 | ||||
-rw-r--r-- | ext/opcache/tests/bug78937_3.phpt | 24 | ||||
-rw-r--r-- | ext/opcache/tests/bug78937_4.phpt | 22 | ||||
-rw-r--r-- | ext/opcache/tests/bug78937_5.phpt | 23 | ||||
-rw-r--r-- | ext/opcache/tests/bug78937_6.phpt | 25 | ||||
-rw-r--r-- | ext/opcache/tests/preload_bug78937.inc | 8 |
10 files changed, 162 insertions, 2 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 7d35a92ade..b6a120c94b 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1068,8 +1068,12 @@ ZEND_API int do_bind_class(zval *lcname, zend_string *lc_parent_name) /* {{{ */ if (UNEXPECTED(!zv)) { ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname)); - ZEND_ASSERT(ce && "Class with lcname should be registered"); - 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)); + if (ce) { + 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)); + } else { + ZEND_ASSERT(EG(current_execute_data)->func->op_array.fn_flags & ZEND_ACC_PRELOADED); + zend_error_noreturn(E_ERROR, "Class %s wasn't preloaded", Z_STRVAL_P(lcname)); + } return FAILURE; } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index b170201372..87d475bf18 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7306,6 +7306,11 @@ ZEND_VM_HANDLER(146, ZEND_DECLARE_ANON_CLASS, ANY, ANY, CACHE_SLOT) if (UNEXPECTED(ce == NULL)) { zend_string *rtd_key = Z_STR_P(RT_CONSTANT(opline, opline->op1)); zv = zend_hash_find_ex(EG(class_table), rtd_key, 1); + if (UNEXPECTED(zv == NULL)) { + SAVE_OPLINE(); + ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_PRELOADED); + zend_error_noreturn(E_ERROR, "Anonymous class wasn't preloaded"); + } ZEND_ASSERT(zv != NULL); ce = Z_CE_P(zv); if (!(ce->ce_flags & ZEND_ACC_LINKED)) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 3d10728415..14e1314bcb 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2446,6 +2446,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_CLASS_SPEC_HANDLE if (UNEXPECTED(ce == NULL)) { zend_string *rtd_key = Z_STR_P(RT_CONSTANT(opline, opline->op1)); zv = zend_hash_find_ex(EG(class_table), rtd_key, 1); + if (UNEXPECTED(zv == NULL)) { + SAVE_OPLINE(); + ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_PRELOADED); + zend_error_noreturn(E_ERROR, "Anonymous class wasn't preloaded"); + } ZEND_ASSERT(zv != NULL); ce = Z_CE_P(zv); if (!(ce->ce_flags & ZEND_ACC_LINKED)) { diff --git a/ext/opcache/tests/bug78937_1.phpt b/ext/opcache/tests/bug78937_1.phpt new file mode 100644 index 0000000000..1125ad4eb0 --- /dev/null +++ b/ext/opcache/tests/bug78937_1.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #78937.1 (Preloading unlinkable anonymous class can segfault) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +opcache.preload={PWD}/preload_bug78937.inc +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php +class Bar { +} +var_dump(foo()); +?> +--EXPECTF-- +Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6 + +Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 + +Fatal error: Anonymous class wasn't preloaded in %spreload_bug78937.inc on line 3 + diff --git a/ext/opcache/tests/bug78937_2.phpt b/ext/opcache/tests/bug78937_2.phpt new file mode 100644 index 0000000000..880063298b --- /dev/null +++ b/ext/opcache/tests/bug78937_2.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #78937.2 (Preloading unlinkable anonymous class can segfault) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +opcache.preload={PWD}/preload_bug78937.inc +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php +include(__DIR__ . "/preload_bug78937.inc"); +class Bar { +} +var_dump(foo()); +?> +--EXPECTF-- +Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6 + +Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 +object(class@anonymous)#%d (0) { +}
\ No newline at end of file diff --git a/ext/opcache/tests/bug78937_3.phpt b/ext/opcache/tests/bug78937_3.phpt new file mode 100644 index 0000000000..1c706e237d --- /dev/null +++ b/ext/opcache/tests/bug78937_3.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #78937.3 (Preloading unlinkable anonymous class can segfault) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +opcache.preload={PWD}/preload_bug78937.inc +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php +include(__DIR__ . "/preload_bug78937.inc"); +var_dump(foo()); +?> +--EXPECTF-- +Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6 + +Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 + +Fatal error: Uncaught Error: Class 'Bar' not found in %spreload_bug78937.inc:3 +Stack trace: +#0 %sbug78937_3.php(3): foo() +#1 {main} + thrown in %spreload_bug78937.inc on line 3 diff --git a/ext/opcache/tests/bug78937_4.phpt b/ext/opcache/tests/bug78937_4.phpt new file mode 100644 index 0000000000..b555516d00 --- /dev/null +++ b/ext/opcache/tests/bug78937_4.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #78937.4 (Preloading unlinkable anonymous class can segfault) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +opcache.preload={PWD}/preload_bug78937.inc +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php +class Bar { +} +bar(); +var_dump(new Foo); +?> +--EXPECTF-- +Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6 + +Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 + +Fatal error: Class foo wasn't preloaded in %spreload_bug78937.inc on line 6
\ No newline at end of file diff --git a/ext/opcache/tests/bug78937_5.phpt b/ext/opcache/tests/bug78937_5.phpt new file mode 100644 index 0000000000..f9f01a2a26 --- /dev/null +++ b/ext/opcache/tests/bug78937_5.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #78937.5 (Preloading unlinkable anonymous class can segfault) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +opcache.preload={PWD}/preload_bug78937.inc +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php +include(__DIR__ . "/preload_bug78937.inc"); +class Bar { +} +bar(); +var_dump(new Foo); +?> +--EXPECTF-- +Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6 + +Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 +object(Foo)#%d (0) { +}
\ No newline at end of file diff --git a/ext/opcache/tests/bug78937_6.phpt b/ext/opcache/tests/bug78937_6.phpt new file mode 100644 index 0000000000..28dcb0ce53 --- /dev/null +++ b/ext/opcache/tests/bug78937_6.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #78937.6 (Preloading unlinkable anonymous class can segfault) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +opcache.preload={PWD}/preload_bug78937.inc +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php +include(__DIR__ . "/preload_bug78937.inc"); +bar(); +var_dump(new Foo); +?> +--EXPECTF-- +Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6 + +Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3 + +Fatal error: Uncaught Error: Class 'Bar' not found in %spreload_bug78937.inc:6 +Stack trace: +#0 %sbug78937_6.php(3): bar() +#1 {main} + thrown in %spreload_bug78937.inc on line 6 diff --git a/ext/opcache/tests/preload_bug78937.inc b/ext/opcache/tests/preload_bug78937.inc new file mode 100644 index 0000000000..7da2dc3227 --- /dev/null +++ b/ext/opcache/tests/preload_bug78937.inc @@ -0,0 +1,8 @@ +<?php +function foo() { + return new class extends Bar {}; +} +function bar() { + class Foo extends Bar { + } +} |