Skip to content

Assertion failure in zend_hash_del with HashTable refcount inconsistency #20855

Open

Description

@vi3tL0u1s

Description

The following code:

<?php
$c = new ReflectionClass('stdClass');
ob_start(fn() => serialize($GLOBALS), 1);
$array = [$c];
unset($array[$x]);
php: /path/to/php-src/Zend/zend_hash.c:1556: zend_hash_del: Assertion `(zend_gc_refcount(&(ht)->gc) == 1) || ((ht)->u.flags & (1<<6))' failed.
Aborted

Commit

5472cac806a

Configurations

CC="clang" CXX="clang++" CFLAGS="-fsanitize=address -g -O0" CXXFLAGS="-fsanitize=address -g -O0" ./configure --enable-debug --enable-address-sanitizer --disable-shared --with-pic

PHP Version

PHP 8.6.0-dev (cli) (built: Jan  7 2026 13:33:43) (NTS DEBUG)
Copyright (c) The PHP Group
Zend Engine v4.6.0-dev, Copyright (c) Zend Technologies
    with Zend OPcache v8.6.0-dev, Copyright (c), by Zend Technologies

Operating System

Ubuntu 22.04

Activity

  1. devnexen commented on Jan 7, 2026

    @devnexen
    Member
    #0  __pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=0) at ./nptl/pthread_kill.c:44
    #1  __pthread_kill_internal (threadid=<optimized out>, signo=6) at ./nptl/pthread_kill.c:89
    #2  __GI___pthread_kill (threadid=<optimized out>, signo=signo@entry=6) at ./nptl/pthread_kill.c:100
    #3  0x00007ffff6845e2e in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
    #4  0x00007ffff6828888 in __GI_abort () at ./stdlib/abort.c:77
    #5  0x00007ffff68287f0 in __assert_fail_base (fmt=<optimized out>, assertion=<optimized out>, file=<optimized out>, line=<optimized out>, function=<optimized out>) at ./assert/assert.c:118
    #6  0x000055555e21ac5e in zend_hash_del (ht=0x7bfff284c6c0, key=0x7c2ff4de1cf0) at /home/dcarlier/Contribs/php-src/Zend/zend_hash.c:1556
    #7  0x000055555dd5c38d in ZEND_UNSET_DIM_SPEC_CV_CV_TAILCALL_HANDLER (execute_data=0x7bfff2807020, opline=0x7bfff2893268) at Zend/zend_vm_execute.h:111422
    #8  0x000055555d46d93f in execute_ex (ex=0x7bfff2807020) at Zend/zend_vm_execute.h:116212
    #9  0x000055555d46f9bf in zend_execute (op_array=0x7bfff2889000, return_value=0x0) at Zend/zend_vm_execute.h:121924
    #10 0x000055555e690e40 in zend_execute_script (type=8, retval=0x0, file_handle=0x7fffffffc300) at /home/dcarlier/Contribs/php-src/Zend/zend.c:1981
    #11 0x000055555cb45f93 in php_execute_script_ex (primary_file=0x7fffffffc300, retval=0x0) at /home/dcarlier/Contribs/php-src/main/main.c:2645
    #12 0x000055555cb46e79 in php_execute_script (primary_file=0x7fffffffc300) at /home/dcarlier/Contribs/php-src/main/main.c:2685
    #13 0x000055555e6a270f in do_cli (argc=2, argv=0x7c2ff4de1ba0) at /home/dcarlier/Contribs/php-src/sapi/cli/php_cli.c:951
    #14 0x000055555e69e6b2 in main (argc=2, argv=0x7c2ff4de1ba0) at /home/dcarlier/Contribs/php-src/sapi/cli/php_cli.c:1362
    
  2. iluuu1994 commented on Jan 7, 2026

    @iluuu1994
    Member

    Looks like more of #20018.

    • unset() separates $array
    • $x emits an undefined variable warning
    • This emits output and calls serialize($GLOBALS).
    • Which throws an exception because ReflectionClass is not serializable
    • Which stores the cloned $GLOBALS in the exception args
    • Which holds a reference to $array
    • Eventually asserting because RC != 1

    @arnaud-lb I'll let it up to you whether this is unique enough to keep.

  3. arnaud-lb commented on Jan 7, 2026

    @arnaud-lb
    Member

    I agree that this falls in #20018. It's a bit different than user error handlers, but it's still related to side effects of errors.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions