3rsh1
/single dog/college student/ctfer
3rsh1's Blog

PHP变量解析复杂规则语法

//1
// {string}    string为变量名{'a'.'a'}="test1";
echo aa."\n";
//2.
function A(){
    echo "test2"."\n";
    return 'aa';
}
echo "heihei,{{A()}},aa";
echo "{aa},aa,{aa}";
echo '{aa},aa,{aa}';
//3.string1 = <<<GOD
我有一只小毛驴,我从来也不骑。
有一天我心血来潮,骑着去赶集。
我手里拿着小皮鞭,我心里正得意。
不知怎么哗啦啦啦啦,我摔了一身泥.
GOD;
echo string1;
echo "{aa}hhh";

结果:
test1

test2
heihei,test1,test1
test1,test1,test1
{aa},aa,{$aa}

我有一只小毛驴,我从来也不骑。
有一天我心血来潮,骑着去赶集。
我手里拿着小皮鞭,我心里正得意。
不知怎么哗啦啦啦啦,我摔了一身泥.test1hhh

之前在做一道preg_match()/e模式引起的代码执行的题目中遇到的一个蛮有意思的特性,然后今天晚上在乱看的时候刚好也看到篇文章,因此这里就记录一下吧。

当字符串用双引号或heredoc结构定义时,其中的变量将会被解析。共有两种语法规则,一种简单规则,一种复杂规则,这里讨论复杂规则。

复杂规则语法的显著标记是用花括号包围的表达式。任何具有string表达的标量变量,数组单元或对象属性都可使用此语法,表达方式{var_name}或{var_name}。

和2中最后两行代码差不多,双引号中的${aa},{$aa},$aa,都是作为变量被解析的,但是单引号没有这个效果。其中的{}用来标记变量的边界。其中的heredoc结构就是代码中的3,首先<<<表明是string类型,然后紧接着的大写字符表示内容的边界,开头和结束需要相同。

在引用的这部分话的第二段指出,复杂规则语法的显著标记是用花括号包围的表达式,任何具有string标答的标量变量等都可以用此语法。那么我们思考既然是表达式,且在${}的形式中{}内只要是字符串就可以了,很容易想到代码1,'a'+'a'='aa',可以用来作为变量名,显然也是可以的。那么里面放置函数可以吗?调用的是函数的输出值还是返回值呢?

可以关注代码2,运行结果中我们发现在最后的echo前,A()函数首先被执行,个人理解是首先echo的内容要确定,故要将变量的值补充进字符串内去,所以要确定变量的值就要提前执行A()函数。执行之后我们发现函数返回的值作为变量的名字继续寻找对应的变量,最后输出$aa对应的值。我们需要注意的是这里首先是执行完函数的,意味着不管变量存不存在都会先执行函数。看到这里我们肯定就会想到一些奇怪的操作了,比如函数的名字为ABC,执行函数:{${('A'.'B'.'C')()}}

那么现在再来探讨一下若是返回值并不是一个字符串会怎么办:

var_dump("{${phpinfo()}}");
//string(0) ""

可能在新版本中${}形式被作为执行函数的一种形式,因此找不到对应的变量并不会报错。但是在参考文章中,对于返回的非字符串类型的值会被强制转换为字符串类型的值。

参考链接:

https://www.anquanke.com/post/id/176331

s1ye师傅nb!

发表评论

textsms
account_circle
email

3rsh1's Blog

PHP变量解析复杂规则语法
//1 // ${string} string为变量名 ${'a'.'a'}="test1"; echo $aa."\n"; //2. function A(){ echo "test2"."\n"; return 'aa'; } echo "heihei,{${A()}},$aa"; echo "${aa},$aa…
扫描二维码继续阅读
2020-08-05