源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

PHP错误抑制符(@)导致引用传参失败Bug的分析

  • 时间:2021-02-01 15:25 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:PHP错误抑制符(@)导致引用传参失败Bug的分析
看下面的例子:
[url=http://bugs.php.net/bug.php?id=47623]http://bugs.php.net/bug.php?id=47623[/url], 但PHP官方还没有解决, 也没有给出答复. 没办法, 只能自己分析了, 之前我曾经在文章中介绍过错误抑制符的原理( [url=http://www.1sucai.cn/article/27023.htm]深入理解PHP原理之错误抑制与内嵌HTML[/url]), 从原理上来说, 错误抑制只是修改了error_reporting的level, 按理来说不会影响到上下文之间的函数调用的机制. 只能通过实地试验了. 经过gdb跟踪, 发现在使用了错误移植符以后, 函数调用前的传参opcode不同:
[u]复制代码[/u] 代码如下:
//没有使用错误抑制符的时候 OPCODE = SEND_REF //使用了错误抑制符号以后 OPCODE = SEND_VAR_NO_RE
问题初步定位了, 但是造成这种差异的原因又是什么呢? 既然OPCODE不同, 那么肯定是在语法分析的阶段, 走了不同的分支了, 想到这一层, 问题也就好定位了, 原来, PHP语法分析阶段, 把形如 “@”+expr的条目, 规约成了expr_without_variable, 而这种节点的意义就是没有变量的值, 也就是字面值, 我们都知道字面值是不能传递引用的(因为它不是变量), 所以, 就会导致这种差异. 具体过程如下: 1. 语法分析阶段:
[u]复制代码[/u] 代码如下:
expr_without_variable: //...有省略 | '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; } //此处走了ZEND_SEND_VAL分支 non_empty_function_call_parameter_list: expr_without_variable { ....} //错误的走了这个分支 | variable {..... } //正常情况
所以导致在编译期间, 生成了不同的OPCODE, 也导致了问题的表象. 最后, 我已经把原因在PHP的这个bug页做了说明, 有兴趣的可以去看看我的烂英语水平. 最后谢谢cici网友提供的这个有趣的问题.
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部