Edit report at https://bugs.php.net/bug.php?id=65352&edit=1

 ID:                 65352
 Comment by:         seyferseed at mail dot ru
 Reported by:        seyferseed at mail dot ru
 Summary:            Method Closure::bind() can access private property
                     of object
 Status:             Open
 Type:               Bug
 Package:            Class/Object related
 Operating System:   Linux
 PHP Version:        5.4.17
 Block user comment: N
 Private report:     N

 New Comment:

For PHP, yes, solved. But not for logic. I believe that to change the link to 
private property is very wrong. Should generate an error.


Previous Comments:
------------------------------------------------------------------------
[2013-07-31 04:30:13] mail+php at requinix dot net

>$bar = $foo->getBar();
Simply making the function return by reference is not enough: you have to 
assign 
by reference too. Otherwise the function returns a reference, yes, but your 
assignment makes a copy. You need both of the &s.

http://php.net/language.references.return
The first note on the page says exactly that.

Your version with Closure::bind() had both. That's why it worked.

Resolved?

------------------------------------------------------------------------
[2013-07-31 02:19:17] seyferseed at mail dot ru

If i'm add & there

$bar = & $foo->getBar();
$bar = "tab";
echo $foo->getBar();

I really can change Private $foo to "tab". I'm so confused... 

I'm expected 
Fatal error: Cannot access private property

But by reference there is no error.

Maybe this is PHP "feature" and there is no bug.

------------------------------------------------------------------------
[2013-07-31 02:14:11] seyferseed at mail dot ru

But if i'm add this function to class Foo by code it in class, i can't access 
private property! And this is right. You say, that my Getter function used in 
Closure::bind() can change (like Setter) private property and this is right? 
I don't think so.

Example:

class Foo
{
    private $bar = 'baz';

    public function &getBar()
    {
                return $this->bar;
    }
}

$foo = new Foo();

$bar = $foo->getBar();
$bar = "tab";
echo $foo->getBar();

It's still "bar". And i don't know how i can change Private property of class 
by 
reference in this case. It will be wrong, if i can. 

And now i'm take my getter

public function &getBar()
    {
                return $this->bar;
    }

Put it in Closure::bind() and i can change Private property. This is really 
wrong.
If i can change it only in function, that binded to Closure::bind(), like

$value = & Closure::bind(function & () use ($property) {

        $this->property = "tab";
        return $this->$property; 
    }, $object, $object)->__invoke();

It's okay, becouse it statically inside Foo. 

But Client code can change Private property by reference! Is that right?

------------------------------------------------------------------------
[2013-07-30 18:09:38] mail+php at requinix dot net

As noted in Closure::bind(),

"public static Closure Closure::bind ( Closure $closure , object $newthis [, 
mixed 
$newscope = 'static' ] )

newscope
The class scope to which associate the closure is to be associated, or 'static' 
to 
keep the current one. If an object is given, the type of the object will be 
used 
instead. This determines the visibility of protected and private methods of the 
bound object."

You changed the scope of the function to be that of inside $foo. Naturally it 
would have access to private members. If you don't want it to do that then omit 
newscope=$object.

------------------------------------------------------------------------
[2013-07-29 04:39:42] seyferseed at mail dot ru

Description:
------------
Method Closure::bind() can access private property of object.

And modify it by reference. It is a violation of encapsulation.

See script for example. http://3v4l.org/JE0eX

Test script:
---------------
<?php

class Foo
{
    private $bar = 'baz';
}

$reader = function & ($object, $property) {
    $value = & Closure::bind(function & () use ($property) { 
        return $this->$property; 
    }, $object, $object)->__invoke();

    return $value;
};

$foo = new Foo();
$bar = & $reader($foo, 'bar');
$bar = 'tab';

var_dump($foo);

Expected result:
----------------
Fatal error: Cannot access private property Foo::$bar in /in/JE0eX on line 8

Actual result:
--------------
Output for 5.4.0 - 5.5.1

object(Foo)#2 (1) {
  ["bar":"Foo":private]=>
  &string(3) "tab"
}


------------------------------------------------------------------------



-- 
Edit this bug report at https://bugs.php.net/bug.php?id=65352&edit=1

Reply via email to