php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79373 uninitialized typed property cannot accessed in __get magic method
Submitted: 2020-03-12 16:56 UTC Modified: 2020-04-13 15:08 UTC
From: consatan at gmail dot com Assigned:
Status: Not a bug Package: Class/Object related
PHP Version: 7.4.3 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: consatan at gmail dot com
New email:
PHP Version: OS:

 

 [2020-03-12 16:56 UTC] consatan at gmail dot com
Description:
------------
A uninitialized typed property cannot accessed in __get method until unset() it. Test on 7.4.0~7.4.3, 7.4.0 is works.

Test script:
---------------
<?php
class Foo {
    public int $bar;
    
    public function __get($name) {
        if ('bar' === $name) {
            return $this->bar = 1;
        }
    }
}

$foo1 = new Foo();
var_dump($foo1);
var_dump($foo1->bar);

$foo2 = new Foo();
var_dump($foo2);
unset($foo2->bar);
var_dump($foo2);
var_dump($foo2->bar);

Expected result:
----------------
object(Foo)#1 (0) {
  ["bar"]=>
  uninitialized(int)
}
int(1)

object(Foo)#2 (0) {
  ["bar"]=>
  uninitialized(int)
}
object(Foo)#2 (0) {
  ["bar"]=>
  uninitialized(int)
}
int(1)

Actual result:
--------------
object(Foo)#1 (0) {
  ["bar"]=>
  uninitialized(int)
}

Warning: Uncaught Error: Typed property Foo::$bar must not be accessed before initialization in php shell code:1
Stack trace:
#0 {main}
  thrown in php shell code on line 1

object(Foo)#2 (0) {
  ["bar"]=>
  uninitialized(int)
}
object(Foo)#2 (0) {
  ["bar"]=>
  uninitialized(int)
}
int(1)

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-03-12 17:12 UTC] beberlei@php.net
-Status: Open +Status: Not a bug
 [2020-03-12 17:12 UTC] beberlei@php.net
Your example seems to be wrong, you are not accessing Foo::$bar through __get, because its public. I assume its an error while making the example small and contained.

However the behavior here is correct regardless of __get or public access. You cannot access an uninitialized typed variable anywhere, before initializing it and this error represents that.
 [2020-04-13 14:47 UTC] ocramius@php.net
Note: while this may or may not be interpreted as a bug, it is still a major BC break. In practice, a PHP 7.4.0 -> 7.4.1 upgrade requires changes in how type properties (public or private) are being shadowed for lazy-loading purposes.
 [2020-04-13 15:08 UTC] requinix@php.net
> Note: while this may or may not be interpreted as a bug, it is still a major BC break. In practice, a
> PHP 7.4.0 -> 7.4.1 upgrade requires changes in how type properties (public or private) are being
> shadowed for lazy-loading purposes.
And in an ideal world the behavior seen in 7.4.0 would not have made it to the release. But it did. And it was incorrect: initialized and accessible are two different and separate concepts. And __get/etc. are about accessibility.

Better to fix the bug immediately and break the early adopters than to let it live until 7.5/8.0 where it would create even larger problems.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Dec 22 08:01:29 2024 UTC