doushan1863 2019-03-28 12:47
浏览 69

我想我发现了一个来自ReflectionProperty的setValue的bug

I'm working on a function to recursively remove arrays and objects recursively. The problem is that certain recursions may be inside private properties of objects.

below is what I tried as well as the entries I tried to use.

this is my entrie

class TestOBJ{

    private $fooClosure = null;
    public $bar = 5;
    private $myPrivateRecursion = null;
    private $aimArrayAndContainsRecursion = [];

    public function __construct()
    {
        $this->fooClosure = function(){
            echo 'pretty closure';
        };
    }

    public function setMyPrivateRecursion(&$obj){
        $this->myPrivateRecursion = &$obj;
    }

    public function setObjInsideArray(&$obj){
        $this->aimArrayAndContainsRecursion[] = &$obj;
    }
}

$std = new stdClass();
$std->std = 'any str';
$std->obj = new stdClass();
$std->obj->other = &$std;

$obj = new TestOBJ();
$obj->bar = new TestOBJ();
$obj->bar->bar = 'hey brow, please works';
$obj->bar->setMyPrivateRecursion($std);

my entrie is var $obj

and this is my function / solution

function makeRecursionStack($vector, &$stack = [], $from = null)
{
    if ($vector) {
        if (is_object($vector) && !in_array($vector, $stack, true) && !is_callable($vector)) {
            $stack[] = &$vector;
            if (get_class($vector) === 'stdClass') {
                foreach ($vector as $key => $value) {
                    if (in_array($vector->{$key}, $stack, true)) {
                        $vector->{$key} = null;
                    } else {
                        $vector->{$key} = $this->makeRecursionStack($vector->{$key}, $stack, $key);
                    }
                }
                return $vector;
            } else {
                $object = new \ReflectionObject($vector);
                $reflection = new \ReflectionClass($vector);
                $properties = $reflection->getProperties();
                if ($properties) {
                    foreach ($properties as $property) {
                        $property = $object->getProperty($property->getName());
                        $property->setAccessible(true);
                        if (!is_callable($property->getValue($vector))) {
                            $private = false;
                            if ($property->isPrivate()) {
                                $property->setAccessible(true);
                                $private = true;
                            }

                            if (in_array($property->getValue($vector), $stack, true)) {
                                $property->setValue($vector, null);
                            } else {
                                //if($property->getName() === 'myPrivateRecursion' && $from === 'bar'){
                                //$get = $property->getValue($vector);
                                //$set = $this->makeRecursionStack($get, $stack, $property->getName());                                
                                //$property->setValue($vector, $set);
                                //pre_clear_buffer_die($property->getValue($vector));
                                //}
                                $property->setValue($vector, $this->makeRecursionStack($property->getValue($vector), $stack, $property->getName()));
                            }

                            if ($private) {
                                $property->setAccessible(false);
                            }
                        }
                    }
                }
                return $vector;
            }
        } else if (is_array($vector)) {
            $nvector = [];
            foreach ($vector as $key => $value) {
                $nvector[$key] = $this->makeRecursionStack($value, $stack, $key);
            }
            return $nvector;
        } else {
            if (is_object($vector) && !is_callable($vector)) {
                return null;
            }
        }
    }
    return $vector;
}

The place where I have comments is where I noticed the problem. if the If is not commented there $get would receive a stdClass that has recursion and this works perfectly and $set would receive the stdClass without recursion. In that order.

$get =

$set =

After this lines

$property->setValue($vector, $set);
pre_clear_buffer_die($property->getValue($vector));

i obtain this

I try to put other value like an bool or null inside property and after set the $set but it's not works.

P.S: pre_clear_buffer_die kill php buffer, init other buffer and show var inside a <pre> after exit from script. Is an debugger function.

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
    • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝
    • ¥20 腾讯企业邮箱邮件可以恢复么
    • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
    • ¥15 错误 LNK2001 无法解析的外部符号
    • ¥50 安装pyaudiokits失败
    • ¥15 计组这些题应该咋做呀
    • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?
    • ¥15 让node服务器有自动加载文件的功能
    • ¥15 jmeter脚本回放有的是对的有的是错的