php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79192 unset does not unset uninitialized typed properties completely
Submitted: 2020-01-29 17:12 UTC Modified: 2020-01-30 09:15 UTC
Votes:1
Avg. Score:3.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: raincomplain at outlook dot com Assigned:
Status: Not a bug Package: Class/Object related
PHP Version: 7.4.2 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 this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: raincomplain at outlook dot com
New email:
PHP Version: OS:

 

 [2020-01-29 17:12 UTC] raincomplain at outlook dot com
Description:
------------
After unsetting an uninitialized typed property any attempt to modify that property will still generate a fatal error an unset seems to set that property to null which is another issue. The later can be illustrated after adding the magic method __get.





 

Test script:
---------------
**Without __get**
<?php
class Foo
{
    public int $bar;

    public function __set($prop, $val) {
        throw new Exception('Dynamic properties are not allowed');
    }

}

$f = new Foo();
unset($f->bar);
echo $f->bar

?>

**With __get**

class Foo
{
    public int $bar;

    public function __set($prop, $val) {
        throw new Exception('Dynamic properties are not allowed');
    }

    public function __get($name)
    {
        echo 'works'.PHP_EOL;
    }
}

$f = new Foo();
unset($f->bar);
echo $f->bar

Expected result:
----------------
The expected behavior is to emit a notice (PHP Notice:  Undefined property: Foo::$bar) or prevent unsetting uninitialized typed properties in the first place.

Actual result:
--------------
**Without __get**

Typed property Foo::$bar must not be accessed before initialization


**With __get**

works
PHP Fatal error:  Uncaught TypeError: Typed property Foo::$bar must be int, null used

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-01-29 17:32 UTC] raincomplain at outlook dot com
-Package: Testing related +Package: Class/Object related
 [2020-01-29 17:32 UTC] raincomplain at outlook dot com
Changing bug package
 [2020-01-30 09:05 UTC] raincomplain at outlook dot com
I would also add that if a property accepts null value 

public ?int $bar;

Then unsetting it should work even if it's not initialized, since unsetting it would set it to null.

But what we saw here is totally unexpected behavior. If unsetting it is not allowed then why magic methods are triggered?
 [2020-01-30 09:15 UTC] nikic@php.net
-Status: Open +Status: Not a bug
 [2020-01-30 09:15 UTC] nikic@php.net
Unsetting of declared properties is allowed **only** for the purpose of lazy initialization patterns. Getting magic methods to be called is the whole point of doing the unset.

We hope to forbid unsetting of declared properties in PHP 8, after providing some alternative mechanism for lazy initialization.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Mar 29 04:01:29 2024 UTC