Skip to content

Segfault in ZEND_NEW with tracing JIT on 8.5.12 cli-server: user class with NULL default_object_handlers #25076

Closed as not planned

Description

@jeanmarcos-dev

Description

The built-in server (php -S, PHP_CLI_SERVER_WORKERS=4) running the web API tests of a Magento 2.4.9 app segfaults now and then on GitHub Actions. It always happens on the first request that places an order, when pelago/emogrifier does new Sabberworm\CSS\RuleSet\DeclarationBlock() to inline the e-mail CSS.

It only happens with the tracing JIT on. Same commit, REST suite only:

opcache jit runs crashes
on 1235, 256M buffer 20 3
on disable 20 0
off - 5 0

All three crashes left a core, and in each one a worker faults at the same place:

#0 ZEND_NEW_SPEC_CONST_UNUSED_HANDLER  Zend/zend_vm_execute.h:11321
#1 execute_ex
#2 zend_call_function
#3 zif_call_user_func_array
#4 execute_ex
#5 zend_call_function
#6 zif_call_user_func
#7 execute_ex
#8 zend_execute_script
#9 php_cli_server_dispatch_router

The faulting instruction is call *0x80(%rax) with rax = NULL, i.e. obj->handlers->get_constructor. The class entry of DeclarationBlock is a linked user class (type = 2, ce_flags = 0x441208) with create_object = NULL and default_object_handlers = NULL, so the new object gets handlers == NULL.

In one run a second worker died 8 seconds later inside the JIT:

#0 zend_jit_cleanup_func_info  ext/opcache/jit/zend_jit.c:3017
#1 zend_jit_cleanup_func_info  ext/opcache/jit/zend_jit.c:3041
#2 zend_real_jit_func          (trigger=3)
#3 zend_jit_hot_func           ext/opcache/jit/zend_jit.c:3234

I can't reproduce it locally with the same binary and ini (12 cold runs of the crashing test class with the JIT on), and I don't have a standalone script. Not sure whether it is related to GH-24488, which is also an 8.5.12 heap regression; Magento uses SimpleXML heavily. I still have the cores and the matching dbgsym, and can run extra debug steps in CI if that helps.

Setup:

  • Build: shivammathur/setup-php php_8.5-nts+ubuntu26.04.tar.zst with the matching dbgsym, ini-file: production, memory_limit=-1. setup-php adds opcache.enable=1, opcache.jit=1235 and opcache.jit_buffer_size=256M; the other OPcache settings are defaults.
  • Server: php -d memory_limit=2G -S 127.0.0.1:8080 -t pub phpserver/router.php
  • Kernel: php[5660]: segfault at 80 ip 0000636e24b978d3 sp 00007ffdb9dc98d0 error 4 in php8.5[5978d3,636e24746000+503000]
Loaded extensions

amqp apcu ast bcmath bz2 calendar Core ctype curl date dba dom ds enchant exif FFI fileinfo filter ftp gd gettext gmp hash iconv igbinary imagick imap intl json ldap lexbor libxml mbstring memcache memcached mongodb msgpack mysqli mysqlnd odbc openssl pcntl pcre PDO pdo_dblib PDO_Firebird pdo_mysql PDO_ODBC pdo_pgsql pdo_sqlite pdo_sqlsrv pgsql Phar posix random readline redis Reflection session shmop SimpleXML snmp soap sockets sodium SPL sqlite3 sqlsrv standard sysvmsg sysvsem sysvshm tidy tokenizer uri xml xmlreader xmlwriter xsl yaml Zend OPcache zip zlib zmq

PHP Version

PHP 8.5.12 (cli) (built: Oct 24 2026 12:37:40) (NTS)
Zend Engine v4.5.12, with Zend OPcache v8.5.12

Operating System

Ubuntu 26.04 (GitHub-hosted ubuntu-latest), x86_64

Activity

  1. iliaal commented on Oct 31, 2026

    @iliaal
    Member

    Duplicate of #24577. A shared interned class-name string can get IS_STR_CLASS_NAME_MAP_PTR set visible to a concurrent worker before its map_ptr offset lands in gc.refcount; the cold-cache worker then reads refcount 2 as the CE-cache slot and instantiates a garbage ce. Here that ce had NULL handlers, so it faulted one deref later in ZEND_NEW at obj->handlers->get_constructor instead of inside GET_CE_CACHE. Your multi-worker php -S over OPcache SHM is the same cold-cache, two-children-compiling race as the FPM report.

    Fixed in 47d5c0c (#24585), merged Oct 27; your Oct 24 nightly predates it (it carries the GH-24488 fix, not this one). The tracing JIT only widens the window. Please retest on an 8.5 build after Oct 27 / 8.5.13.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions