Skip to content

zend_mm_heap corrupted when serializing/unserializing Enum #181

Description

@earthiverse

This one works fine:

enum Random: int
{
    case One = 1;
    case Two = 2;
    case Three = 3;
    case Four = 4;
    case Five = 5;
}

$value = (object)[
    'one' => Random::One
];

$serialized = msgpack_serialize($value);
$unserialized = msgpack_unserialize($serialized);

This one seems to fail with zend_mm_heap corrupted after running

enum Random: int
{
    case One = 1;
    case Two = 2;
    case Three = 3;
    case Four = 4;
    case Five = 5;
}

$value = (object)[
    'one' => Random::One
];

$serialized = msgpack_serialize($value);
$unserialized = msgpack_unserialize($serialized);

$serialized2 = msgpack_serialize($value);
$unserialized = msgpack_unserialize($serialized);

Using the object methods also fails:

$value = (object)[
    'one' => Random::One
];

$packer = new \MessagePack(true);
$unpacker = new \MessagePackUnpacker(true);

$serialized = $packer->pack($value);
$unpacker->feed($serialized);
$unpacker->execute();
$unserialized = $unpacker->data();

$unpacker->reset();

$serialized2 = $packer->pack($value);
$unpacker->feed($serialized);
$unpacker->execute();
$unserialized2 = $unpacker->data();

$unpacker->reset();

Errors in both

PHP 8.4.14 (cli) (built: Oct 24 2025 19:07:34) (NTS)
Copyright (c) The PHP Group
Built by https://github.com/docker-library/php
Zend Engine v4.4.14, Copyright (c) Zend Technologies
    with Zend OPcache v8.4.14, Copyright (c), by Zend Technologies
    with Xdebug v3.4.7, Copyright (c) 2002-2025, by Derick Rethans

and

PHP 8.4.16 (cli) (built: Dec 16 2025 16:03:34) (NTS)
Copyright (c) The PHP Group
Built by Homebrew
Zend Engine v4.4.16, Copyright (c) Zend Technologies
    with Xdebug v3.5.0, Copyright (c) 2002-2025, by Derick Rethans
    with Zend OPcache v8.4.16, Copyright (c), by Zend Technologies

Activity

  1. earthiverse commented on Jan 8, 2026

    @earthiverse
    Author

    earthiverse@ca6d866 made a test to reproduce it, seems more likely to fail when you include the Enum from another file

    php-8.4-debug-nozts

    TEST 145/145 [tests/issue181.phpt]
    ========DIFF========
         Test
    002- OK
    002+ php: /tmp/php-8.4-debug-session-/src/php-8.4.16/Zend/zend_variables.c:133: zval_copy_ctor_func: Assertion `0' failed.
    003+ Aborted (core dumped)
    004+ 
    005+ Termsig=6
    ========DONE========
    FAIL Issue #181 (zend_mm_heap corrupted when serializing/unserializing Enum) [tests/issue181.phpt] 
    

    php-8.4-nodebug-nozts

    TEST 145/145 [tests/issue181.phpt]
    ========DIFF========
         Test
    002- OK
    002+ zend_mm_heap corrupted
    003+ Aborted (core dumped)
    004+ 
    005+ Termsig=6
    ========DONE========
    FAIL Issue #181 (zend_mm_heap corrupted when serializing/unserializing Enum) [tests/issue181.phpt] 
    

    Edit: Tested a fix generated by AI earthiverse@671217f

    It fixed the test case, but I have no idea what it's doing, and I don't want to burden anyone with slop, so I'm just editing my previous comment here.

  2. cracksalad commented on Apr 11, 2026

    @cracksalad
    Contributor

    @earthiverse could you please try and build #184. It could help with your issue as well, but I am not sure about that.

  3. earthiverse commented on Apr 13, 2026

    @earthiverse
    Author

    @earthiverse could you please try and build #184. It could help with your issue as well, but I am not sure about that.

    Seems like it could be different issues...

    Rebased the test I made on your master branch, but my test failed.
    https://github.com/earthiverse/msgpack-php/actions/runs/24319495765

    Rebased your test on the fix that fixed my test, but your test failed.
    https://github.com/earthiverse/msgpack-php/actions/runs/24319566957

  4. cracksalad commented on Apr 13, 2026

    @cracksalad
    Contributor

    @earthiverse could you please try and build #184. It could help with your issue as well, but I am not sure about that.

    Seems like it could be different issues...

    Rebased the test I made on your master branch, but my test failed. https://github.com/earthiverse/msgpack-php/actions/runs/24319495765

    Rebased your test on the fix that fixed my test, but your test failed. https://github.com/earthiverse/msgpack-php/actions/runs/24319566957

    Would have been too easy, I guess. Thanks for testing though.

    The your-tests-my-fix variant's test results look all over the place. I mean 8.1 and 8.4 are mostly satisfied while 8.2 and 8.3 are not. At least the php-8.4-debug-nozts and php-8.4-nodebug-zts tests seem to be fixed compared to the your-tests-no-fix variant. Sadly I can not see the test result details this way. So I will integrate your tests into my version and maybe I am able to extend my fix.

  5. cracksalad commented on Apr 13, 2026

    @cracksalad
    Contributor

    There you go. After hours of looking at the location valgrind points to during serialize, I came to the conclusion that the root cause is in unserialize as you already suggested. At least, I found a cleaner and simpler solution, which does exactly the same as your GC_ADDREF(...) line, but hidden 😁
    I also integrated your test and CI ran successfully.

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