Thanks to visit codestin.com
Credit goes to github.com

Skip to content

LazyProxyTrait breaks classes with missing __unserialize $data parameter type #57470

Closed
@InvisibleSmiley

Description

@InvisibleSmiley

Symfony version(s) affected

6.2.0 and later

Description

If the LazyProxyTrait is used in a class that extends another class which does not have type declaration "array" for the "$data" parameter of method "__unserialize", PHP rejects the result with an error, e.g.:

Fatal error: Declaration of Symfony\Component\VarExporter\LazyProxyTrait::__unserialize(array $data): void must be compatible with X::__unserialize($data) in .../vendor/symfony/var-exporter/LazyProxyTrait.php on line 322

This for example affects all classes extending ArrayObject from laminas/laminas-stdlib:
https://github.com/laminas/laminas-stdlib/blob/3.20.x/src/ArrayObject.php#L468
e.g. ArrayStorage from laminas/laminas-session.

How to reproduce

<?php

declare(strict_types=1);

use Symfony\Component\VarExporter\LazyProxyTrait;

require __DIR__ . '/../vendor/autoload.php';

class X {
    public function __unserialize($data) {}
}

class Y extends X {
    use LazyProxyTrait;
}

Possible Solution

Change signature of LazyProxyTrait::__unserialize to remove the parameter type declaration.
As a result, any kind of signature in target classes will be accepted, see https://3v4l.org/QZKi5

Additional Context

Since ProxyHelper::generateLazyProxy generates a string, you can postprocess it as a workaround until this bug is fixed:

<?php

declare(strict_types=1);

use Laminas\Session\Storage\ArrayStorage;
use Symfony\Component\VarExporter\LazyProxyTrait;
use Symfony\Component\VarExporter\ProxyHelper;

require_once __DIR__ . '/../vendor/autoload.php';

trait UntypedLazyProxyTrait {
    use LazyProxyTrait { __unserialize as private typed__unserialize; }

    public function __unserialize($data): void
    {
        $this->typed__unserialize($data);
    }
}

$proxyCode = ProxyHelper::generateLazyProxy(new ReflectionClass(ArrayStorage::class));
$proxyCode = str_replace(
    'use \Symfony\Component\VarExporter\LazyProxyTrait;',
    'use UntypedLazyProxyTrait;',
    $proxyCode
);
eval('class ArrayStorageProxy'.$proxyCode);

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions