]> granicus.if.org Git - php/commitdiff
Fixed bug #78926: Handle class table reallocation on failed link
authorNikita Popov <nikita.ppv@gmail.com>
Mon, 9 Dec 2019 08:15:27 +0000 (09:15 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 9 Dec 2019 08:15:27 +0000 (09:15 +0100)
When we change back the bucket key on a class linking failure,
make sure to reload the bucket pointer, as the class table may
have been reallocated in the meantime.

Also remove a bogus bucket key change in anon class registration:
We don't actually rename the class in this case anymore, the RTD
key is already the final name.

NEWS
Zend/tests/bug78926.phpt [new file with mode: 0644]
Zend/zend_compile.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index ce5acb513d4c8f8b2b2d011541b49a340e150fd2..787a54613558f782bfd0d9f884b1e75247734d7f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,7 @@ PHP                                                                        NEWS
   . Fixed bug #78898 (call_user_func(['parent', ...]) fails while other
     succeed). (Nikita)
   . Fixed bug #78904 (Uninitialized property triggers __get()). (Nikita)
+  . Fixed bug #78926 (Segmentation fault on Symfony cache:clear). (Nikita)
 
 - GD:
   . Fixed bug #78849 (GD build broken with -D SIGNED_COMPARE_SLOW). (cmb)
diff --git a/Zend/tests/bug78926.phpt b/Zend/tests/bug78926.phpt
new file mode 100644 (file)
index 0000000..5df92bd
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+Bug #78926: Segmentation fault on Symfony cache:clear
+--FILE--
+<?php
+
+spl_autoload_register(function($class) {
+    for ($i = 0; $i < 100; $i++) {
+        eval("class C$i {}");
+    }
+});
+
+try {
+    class B extends A {}
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
+var_dump(class_exists('B', false));
+
+?>
+--EXPECT--
+Class 'A' not found
+bool(false)
index dbbd9119a2cee9cdd4dd3ab201e3219bfb65197d..116fc0b7c539fb52b3f9aa6a08b76fe6f158052f 100644 (file)
@@ -1082,6 +1082,8 @@ ZEND_API int do_bind_class(zval *lcname, zend_string *lc_parent_name) /* {{{ */
        }
 
        if (zend_do_link_class(ce, lc_parent_name) == FAILURE) {
+               /* Reload bucket pointer, the hash table may have been reallocated */
+               zv = zend_hash_find(EG(class_table), Z_STR_P(lcname));
                zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(rtd_key));
                return FAILURE;
        }
index e699e5dc23ac08cb2a1695c605a68d88970e3dfd..b17020137258c75bdc6b86b509fb170e7fc37df2 100644 (file)
@@ -7284,6 +7284,8 @@ ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, CONST)
                                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 {
                                if (zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2))) == FAILURE) {
+                                       /* Reload bucket pointer, the hash table may have been reallocated */
+                                       zv = zend_hash_find(EG(class_table), Z_STR_P(lcname));
                                        zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1));
                                        HANDLE_EXCEPTION();
                                }
@@ -7309,7 +7311,6 @@ ZEND_VM_HANDLER(146, ZEND_DECLARE_ANON_CLASS, ANY, ANY, CACHE_SLOT)
                if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
                        SAVE_OPLINE();
                        if (zend_do_link_class(ce, (OP2_TYPE == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL) == FAILURE) {
-                               zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, rtd_key);
                                HANDLE_EXCEPTION();
                        }
                }
index a0cfc277bdd6855a448f77ea3fd199b2d407aaf7..3d10728415aa787d998d91cf3932bbb09597d79a 100644 (file)
@@ -2451,7 +2451,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_CLASS_SPEC_HANDLE
                if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
                        SAVE_OPLINE();
                        if (zend_do_link_class(ce, (opline->op2_type == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL) == FAILURE) {
-                               zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, rtd_key);
                                HANDLE_EXCEPTION();
                        }
                }
@@ -6395,6 +6394,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_DELAYED_SPEC_CON
                                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 {
                                if (zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2))) == FAILURE) {
+                                       /* Reload bucket pointer, the hash table may have been reallocated */
+                                       zv = zend_hash_find(EG(class_table), Z_STR_P(lcname));
                                        zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1));
                                        HANDLE_EXCEPTION();
                                }