Nested unserialize() can expose an outer object while its __unserialize() data is still being parsed

Ouverte
#25,056 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

Personne n'a encore pris cette issue.

Évaluation

Difficulté
5/5
Temps estimé
Plus d'une semaine
Accessibilité débutants
25/100
Type d'issue
Bug
Clarté
À clarifier
Activité
Active
Stack technique
c, php
Domaine
backend, security

Piste de recherche

The issue provides a PHP reproducer that triggers the bug in php-src's unserialize. Investigate the C parser handling nested unserialize calls and shared reference tables; no specific files are named. A fix requires a design decision on rejecting references versus preserving cyclic payloads, and validation with the reproducer.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

Description

A nested unserialize() call from Serializable::unserialize() shares the outer reference table. An r/R record can therefore resolve to an outer object whose __unserialize() data is still being parsed. At that point __unserialize() has not been queued and cannot be called because the outer parser frame is suspended.

If inner code only stores the object, identity is preserved and it is initialized later. If it accesses the object immediately, it observes incomplete userland properties and could reach uninitialized native state for internal classes.

Unlike GH-19860, this object is not fully parsed, so finishing pending callbacks at the nested boundary cannot fix this case.

Reproducer
<?php
class Outer {
    public string $value;

    public function __unserialize(array $data): void {
        $this->value = "ready";
    }
}

class Legacy implements Serializable {
    public function serialize(): string {
        return "";
    }

    public function unserialize(string $data): void {
        $object = unserialize($data);
        var_dump(isset($object->value));
    }

    public function __serialize(): array {
        return [];
    }

    public function __unserialize(array $data): void {}
}

$result = unserialize("O:5:\"Outer\":1:{i:0;C:6:\"Legacy\":4:{r:1;}}");
echo $result->value, "\n";

Output:

bool(false)
ready
Expected behavior

This needs a separate design decision. Rejecting these references prevents unsafe access, but breaks cyclic payloads that previously retained the object until initialization completed.

Langage dominant
C
Étoiles
41.8k
Forks
8.5k
Merge moyen
2 j 12 h
PR mergées (30 j)
137

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de php/php-src

Toutes les issues de php/php-src

Issues similaires

Plus d'issues C

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.