PHP错误抑制符(@)导致引用传参失败的Bug
2014-07-06 15:58
537 查看
作者: Laruence(
)
本文地址: http://www.laruence.com/2010/05/28/1565.html
转载请注明出处
今天cici网友发来一个问题, 说是在函数调用参数前面使用错误抑制符号(@)的时候, 貌似引用传参就失效了. 他想让我帮他解答为什么.
看下面的例子:
这个问题, 我之前没有遇到过, 所以首先去找找相关资料, 看看有没有现成的答案, Goolge了一番, 发现虽然有人已经向PHP报了类似的Bug:http://bugs.php.net/bug.php?id=47623,
但PHP官方还没有解决, 也没有给出答复.
没办法, 只能自己分析了, 之前我曾经在文章中介绍过错误抑制符的原理( 深入理解PHP原理之错误抑制与内嵌HTML),
从原理上来说, 错误抑制只是修改了error_reporting的level, 按理来说不会影响到上下文之间的函数调用的机制. 只能通过实地试验了.
经过gdb跟踪, 发现在使用了错误移植符以后, 函数调用前的传参opcode不同:
问题初步定位了, 但是造成这种差异的原因又是什么呢?
既然OPCODE不同, 那么肯定是在语法分析的阶段, 走了不同的分支了, 想到这一层, 问题也就好定位了,
原来, PHP语法分析阶段, 把形如 “@”+expr的条目, 规约成了expr_without_variable, 而这种节点的意义就是没有变量的值, 也就是字面值, 我们都知道字面值是不能传递引用的(因为它不是变量), 所以, 就会导致这种差异.
具体过程如下:
1. 语法分析阶段:
所以导致在编译期间, 生成了不同的OPCODE, 也导致了问题的表象.
最后, 我已经把原因在PHP的这个bug页做了说明, 有兴趣的可以去看看我的烂英语水平. 最后谢谢cici网友提供的这个有趣的问题.
)
本文地址: http://www.laruence.com/2010/05/28/1565.html
转载请注明出处
今天cici网友发来一个问题, 说是在函数调用参数前面使用错误抑制符号(@)的时候, 貌似引用传参就失效了. 他想让我帮他解答为什么.
看下面的例子:
<ol style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline; list-style-type: none;"><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><?php</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_variable" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(198, 197, 254);">$array</span> <span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">=</span> <span class="sh_keyword" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(150, 203, 254);">array</span><span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">(</span><span class="sh_number" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(255, 115, 253);">1</span><span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">,</span><span class="sh_number" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(255, 115, 253);">2</span><span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">,</span><span class="sh_number" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(255, 115, 253);">3</span><span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">);</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"> </li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_keyword" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(150, 203, 254);">function</span> <span class="sh_function" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(255, 210, 167);">add</span> <span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">(&</span><span class="sh_variable" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(198, 197, 254);">$arr</span><span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">)</span> <span class="sh_cbracket" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">{</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"> <span class="sh_variable" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(198, 197, 254);">$arr</span><span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">[]</span> <span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">=</span> <span class="sh_number" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(255, 115, 253);">4</span><span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">;</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_cbracket" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">}</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_function" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(255, 210, 167);">add</span><span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">(</span>@<span class="sh_variable" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(198, 197, 254);">$array</span><span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">);</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_function" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(255, 210, 167);">print_r</span><span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">(</span><span class="sh_variable" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(198, 197, 254);">$array</span><span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">);</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);">/**</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);">此时, $array没有改变, 输出:</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);">Array</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);">(</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);"> [0] => 1</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);"> [1] => 2</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);"> [2] => 3</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);">)</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"> </li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);">*/</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_function" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(255, 210, 167);">add</span><span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">(</span><span class="sh_variable" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(198, 197, 254);">$array</span><span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">);</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_function" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(255, 210, 167);">print_r</span><span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">(</span><span class="sh_variable" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(198, 197, 254);">$array</span><span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">);</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);">/**</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);">不使用错误抑制的情况下, 输出正常:</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);">Array</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);">(</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);"> [0] => 1</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);"> [1] => 2</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);"> [2] => 3</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);"> [3] => 4</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);">)</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline; color: rgb(124, 124, 124);">*/</span></li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"><span class="sh_symbol" style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">?></span></li></ol>
这个问题, 我之前没有遇到过, 所以首先去找找相关资料, 看看有没有现成的答案, Goolge了一番, 发现虽然有人已经向PHP报了类似的Bug:http://bugs.php.net/bug.php?id=47623,
但PHP官方还没有解决, 也没有给出答复.
没办法, 只能自己分析了, 之前我曾经在文章中介绍过错误抑制符的原理( 深入理解PHP原理之错误抑制与内嵌HTML),
从原理上来说, 错误抑制只是修改了error_reporting的level, 按理来说不会影响到上下文之间的函数调用的机制. 只能通过实地试验了.
经过gdb跟踪, 发现在使用了错误移植符以后, 函数调用前的传参opcode不同:
<ol style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline; list-style-type: none;"><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">//没有使用错误抑制符的时候</li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">OPCODE = SEND_REF </li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"> </li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">//使用了错误抑制符号以后</li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">OPCODE = SEND_VAR_NO_REF</li></ol>
问题初步定位了, 但是造成这种差异的原因又是什么呢?
既然OPCODE不同, 那么肯定是在语法分析的阶段, 走了不同的分支了, 想到这一层, 问题也就好定位了,
原来, PHP语法分析阶段, 把形如 “@”+expr的条目, 规约成了expr_without_variable, 而这种节点的意义就是没有变量的值, 也就是字面值, 我们都知道字面值是不能传递引用的(因为它不是变量), 所以, 就会导致这种差异.
具体过程如下:
1. 语法分析阶段:
<ol style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline; list-style-type: none;"><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">expr_without_variable:</li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">//...有省略</li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"> | '@' { zend_do_begin_silence(&$1 TSRMLS_CC); }</li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"> expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; }</li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"> </li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">//此处走了ZEND_SEND_VAL分支</li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;">non_empty_function_call_parameter_list:</li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"> expr_without_variable { ....} //错误的走了这个分支</li><li style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline;"> | variable {..... } //正常情况下</li></ol>
所以导致在编译期间, 生成了不同的OPCODE, 也导致了问题的表象.
最后, 我已经把原因在PHP的这个bug页做了说明, 有兴趣的可以去看看我的烂英语水平. 最后谢谢cici网友提供的这个有趣的问题.
相关文章推荐
- PHP错误抑制符(@)导致引用传参失败Bug的分析
- PHP错误抑制符(@)导致引用传参失败Bug的分析
- PHP错误抑制符(@)导致引用传参失败的Bug
- PHP中使用foreach和引用导致程序BUG的问题介绍
- PHP中使用foreach和引用导致程序BUG的问题介绍
- 新浪微博PHP版SDK的BUG,导致20007错误的解决方案
- PHP 数组 foreach引用导致的bug
- PHP中使用foreach和引用导致程序BUG及解决办法
- dll引用错误导致部署失败
- Asp.net Membership的BUG:存储过程错误导致无法更新用户最近活动时间
- CQ的Bug导致服务器出现的jakarta tomcat相关错误
- 一个ArcGIS Javascript API的BUG和处理办法 - 调用两次Draw工具条deactivate方法导致的错误
- IIS 无权查看网页 HTTP 错误 401.2 - 未授权:服务器配置导致登录失败解决方法
- sql语句中导致索引失败的一些错误使用方式
- 基于所提供的凭据,您没有权限查看此目录或网页;HTTP 错误 401.2 - 未授权:服务器配置导致登录失败
- defer属性导致引用JQuery的页面报“浏览器无法打开网站xxx,操作被中止”错误
- 一个ArcGIS Javascript API的BUG和处理办法 - 调用两次Draw工具条deactivate方法导致的错误
- 导致ERP项目实施失败的四种错误实施方法
- 深入理解PHP原理之错误抑制与内嵌HTML
- 关于导致 N70 下载jad安装程序, 出现 "授权失败" 的错误