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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions