[php-src] Issue #21584: Bug: Typed private property initialization flag not updated during dynamic assignment in __unserialize

[email protected] (wheakerd)
Newsgroups php.bugs
Message-ID <HYpa3IkBj6WDCPt0MNkDJ36dZw8aTl0ioIUGFVOSQFU@main.internal.php.net>
Issue: https://github.com/php/php-src/issues/21584
Author: wheakerd

### Description

Description
In PHP 8.4.17, assigning values to typed private properties using dynamic property names (e.g., $this->{$key} = $value) inside the __unserialize method fails to correctly update the property's internal initialization state.

Although `var_dump()` correctly displays the property value and the property is initialized, any attempt to access the property via a getter method results in a fatal error ($parameter must not be accessed before initialization). The Zend Engine's property hash table appears to be updated, but the initialization protection mechanism is not triggered when dynamically accessing private scopes.

PHP Version
PHP 8.4.17 (cli)

Reproduction Script
```php
<?php

class Annotation 
{
    private ?string $method = null;

    public function __construct(string $method) 
    {
        $this->method = $method;
    }

    public function getMethod(): string 
    {
        // This fails even if var_dump shows $this->method has a string value
        if ($this->method === null) {
            throw new \LogicException("Method is null");
        }
        return $this->method;
    }

    public function __serialize(): array
	{
		return get_object_vars($this);
	}

	public function __unserialize(array $data): void
	{
		foreach ($data as $key => $value) {
			if (property_exists($this, $key)) {
				$this->{$key} = $value;
			}
		}
	}
}

// 1. Create and serialize
$obj = new Annotation("index");
$serialized = serialize($obj);

// 2. Unserialize
$unserialized = unserialize($serialized);

// 3. Inspection
echo "Var_dump output:\n";
var_dump($unserialized); 

try {
    echo "\nCalling getMethod(): " . $unserialized->getMethod() . "\n";
} catch (\Throwable $e) {
    echo "\nCaught Exception: " . $e->getMessage() . "\n";
}
```
Expected Result

The output should be:
`Calling getMethod(): index`

Actual Result
`$method must not be accessed before initialization`

(Note: `var_dump` inside the script will show `["method":"Annotation":private]=> string(5) "index"`, proving that the data exists in memory but cannot be accessed.)

Additional Context

- This problem occurs with all visibility type properties.

- Using explicit assignment `$this->method = $data['method']` instead of a `foreach` loop also fails to solve this problem.

### PHP Version

```plain
PHP 8.3.27 (cli) (built: Oct 25 2025 03:25:55) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.3.27, Copyright (c) Zend Technologies
```

### Operating System

Ubuntu 24.04.4 LTS
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.