-
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
Description
Symfony version(s) affected
7.2.0 and up
Description
The logic for generating the JSON metadata file in ResourceCheckerConfigCache generates a PHP unserialization warning if $metadata contains an object that has a property where the class name plus property name combined are more than around 100 characters in length.
This is due to incorrect mangling of the serialized representation in
| $ser = preg_replace_callback('/s:(\d+):"\0[^\0]++\0/', static fn ($m) => 's:'.($m[1] - \strlen($m[0]) + 6).':"', $ser); |
6 is probably some ugly micro-optimization to prevent capturing the matched class name. It seems that the 6 is based on an assumption of 6 'non-removed' characters in the matched string: the s, :, two characters for the serialized string length, another : and a ". However, when the length of the serialized property id (class name surrounded with nullbytes plus property name) exceeds 100, the assumption of two characters for the serialized string length does not hold anymore.
This causes the logic to generate an invalid serialized representation like s:3:"prop", where the indicated string length does not match the actual length of the property name string, and thus causes unserialize() to fail.
How to reproduce
The following script suffices in a project where symfony/config is installed via composer:
<?php
declare(strict_types=1);
require_once "vendor/autoload.php";
class MyResourceWithAVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongName implements \Symfony\Component\Config\Resource\ResourceInterface {
public function __construct(
private readonly string $prop,
) {}
public function __toString(): string {
return "myresource";
}
}
$file = __DIR__ . "/my_cache.php";
$configCache = new \Symfony\Component\Config\ResourceCheckerConfigCache($file);
$metadata = [
new MyResourceWithAVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongName("bar"),
];
$configCache->write("foo", $metadata);Note that the issue disappears when you remove one 'Very' from the class name, bringing the total length back under 100.
Possible Solution
Replace the + 6 by + 4 + \strlen($m[1]), or just capture the removed classname and use its length for the adjustment.
Additional Context
No response