Skip to content

apcu_store()/apcu_fetch() corrupts objects that define __serialize() without __unserialize() — duplicate private+public properties #410

@koftikes

Description

@koftikes

When storing an object via apcu_store() where the class defines __serialize() but not __unserialize(), the object returned by apcu_fetch() is corrupted: it contains both a private property slot (with the default value) and a dynamic public property (with the actual value) under the same name simultaneously. This state is impossible to achieve through normal PHP code.

Environment:
PHP version: 8.4.18
APCu version: 5.1.28
igbinary version: 3.2.16
OS: Linux Ubuntu

APCu config:
apc.entries_hint = 100000
apc.slam_defense = On
apc.gc_ttl = 600
apc.serializer = igbinary
apc.shm_size = 128M
apc.ttl = 3600

Code for reproducing:

<?php
class Foo
{
    public function __construct(private string $name = 'default') {}
    public function __serialize(): array { return ['name' => $this->name]; }
    public function getName(): string { return $this->name; }

    // __unserialize() is intentionally undefined
    // public function __unserialize(array $data): void { $this->name = $data['name']; }
}

$original = new Foo('actual');
apcu_store('test_key', $original);
$restored = apcu_fetch('test_key');

echo "Original name: " . $original->getName() . PHP_EOL;
echo "Restored name: " . $restored->getName() . PHP_EOL;

$arr = (array) $restored;
echo PHP_EOL . "Cast to array (raw keys):" . PHP_EOL;
foreach ($arr as $key => $value) {
    echo "  " . json_encode($key) . " => " . json_encode($value) . PHP_EOL;
}

When apc.serializer = igbinary enabled:
Image

After disabled:
Image

See, two discussions about investigations this bug:
👉 krakjoe/apcu#609
👉 symfony/symfony#63431

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