php / php/php-src

`unserialize` doesn't respect `class_alias` for properties

Ouverte
#18,542 3 commentaires 1 réaction 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Bug Category: Serialization Extension: standard
Langage dominant
C
Étoiles
40.4k
Forks
8.1k
Merge moyen
2 j 13 h
PR mergées (30 j)
96

Description

Description

The following code:

<?php // serialize.php

class Hello {
    public function __construct (
        private readonly int $answer
    ) {}
}

$x = serialize(new Hello(42));
file_put_contents('serialized.bin', $x);
<?php // unserialize.php
class HelloAlias {
    public function __construct (
       public readonly int $answer
    ) {}
}

class_alias(HelloAlias::class, 'Hello');

$x = file_get_contents('serialized.bin');
$z = unserialize($x);
var_dump($z->answer);

Resulted in this output:

PHP Deprecated:  Creation of dynamic property HelloAlias::$answer is deprecated in unserialize-bug/unserialize.php on line 12

Fatal error: Uncaught Error: Typed property HelloAlias::$answer must not be accessed before initialization in unserialize-bug/unserialize.php:13
Stack trace:
#0 {main}
  thrown in unserialize-bug/unserialize.php on line 13

But I expected this output instead:

int(42)

If I look at the serialized.bin file, I can see that for the variable "answer", there is {s:13:"�Hello�answer";i:42;} stored (containing the class without alias).

When I add debug for __unserialize

public function __unserialize (array $arr): void {
    var_dump($arr);
}

I will get this output. The Helloanswer is actually \0Hello\0answer

➜  unserialize-bug php unserialize.php
array(1) {
  ["Helloanswer"]=>
  int(42)
}

Using this naiive fix will work, but is really ugly:

public function __unserialize (array $arr): void {
    foreach ($arr as $k => $v) {
        $key = str_replace("\0Hello\0", '', $k);
        $this->$key = $v;
    }
}
PHP Version
➜  php -v
PHP 8.3.20 (cli) (built: Apr  8 2025 20:21:18) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.3.20, Copyright (c) Zend Technologies
    with Zend OPcache v8.3.20, Copyright (c), by Zend Technologies
Operating System

No response

Guide de contribution

Ouvrir le guide de contribution

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.

Piste de recherche

Commencez par exécuter les scripts fournis serialize.php et unserialize.php avec PHP 8.3.20, puis inspectez serialized.bin et la sortie de débogage de __unserialize afin de suivre la représentation du nom de propriété aliasé. Le travail est terminé lorsque le cas reproduit renvoie int(42) sans créer de propriété dynamique ni laisser la propriété typée non initialisée.

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

Évaluation

Stack technique
php
Domaine
backend
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
À l'abandon
Clarté
Clairement spécifiée
Accessibilité débutants
35/100

Recevez les nouvelles issues par e-mail

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