diff --git a/NEWS b/NEWS index a47e508675c..bf6f7537d84 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,8 @@ PHP NEWS - Core: . Fail early in *nix configuration build script. (hakre) + . Fixed bug GH-16727 (Opcache bad signal 139 crash in ZTS bookworm + (frankenphp)). (nielsdos) - FPM: . Fixed GH-16432 (PHP-FPM 8.2 SIGSEGV in fpm_get_status). (Jakub Zelenka) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 5e79152f257..38d378a4175 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -8043,7 +8043,13 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel) } opline->op1_type = IS_CONST; - LITERAL_STR(opline->op1, lcname); + /* It's possible that `lcname` is not an interned string because it was not yet in the interned string table. + * However, by this point another thread may have caused `lcname` to be added in the interned string table. + * This will cause `lcname` to get freed once it is found in the interned string table. If we were to use + * LITERAL_STR() here we would not change the `lcname` pointer to the new value, and it would point to the + * now-freed string. This will cause issues when we use `lcname` in the code below. We solve this by using + * zend_add_literal_string() which gives us the new value. */ + opline->op1.constant = zend_add_literal_string(&lcname); if (decl->flags & ZEND_ACC_ANON_CLASS) { opline->opcode = ZEND_DECLARE_ANON_CLASS;