Home >Backend Development >PHP Tutorial >Analysis of bugs caused by PHP error suppressor @ causing failure to pass parameters by reference

Analysis of bugs caused by PHP error suppressor @ causing failure to pass parameters by reference

WBOY
WBOYOriginal
2016-07-29 08:45:031076browse

Look at the example below:

Copy the code The code is as follows:


$array = array(1,2,3);
function add (&$arr) {
$arr[] = 4;
}
add(@$array);
print_r($array);
/**
At this time, $array has not changed, output:
Array
(
[0] => 1
[1] => 2
[2] => 3
)
*/
add($array);
print_r($array);
/**
Without error suppression, the output is normal:
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
*/
?>


I have never encountered this problem before, so I first looked for relevant information to see if there is any ready answer. I googled it and found that although someone has reported a similar problem to PHP Bug: http://bugs.php.net/bug.php?id=47623, but PHP official has not solved it yet, and has not given a reply.

There is no other way, I can only analyze it myself. I have mentioned it in the article before The principle of error suppression is introduced in (In-depth understanding of PHP principles of error suppression and embedded HTML). In principle, error suppression only modifies the level of error_reporting, and logically speaking, it will not affect function calls between contexts. Mechanism. It can only be tested in the field.

After tracking by gdb, it was found that after using the wrong transplantation character, the parameter opcode before the function call is different:

Copy the code The code is as follows:


//No When using the error suppressor
OPCODE = SEND_REF
//After using the error suppressor
OPCODE = SEND_VAR_NO_RE


The problem has been initially located, but what is the reason for this difference?
Since the OPCODE is different, then it must be It was during the syntax analysis stage that we took different branches. Thinking of this level, the problem can be easily identified.
It turns out that in the PHP syntax analysis stage, entries in the form of "@" + expr are reduced to expr_without_variable. The meaning of this kind of node is that there is no variable value, that is, a literal value. We all know that a literal value cannot pass a reference (because it is not a variable), so this difference will result.
The specific process is as follows:
1 . Grammar analysis phase: 析 Copy code

Code as follows: expr_without_variable: // ... There are omitted

| '@' {zend_begin_silence (& $ 1 TSRMLS_CC);}

expr { lence (& $ 1 TSRMLS_CC); $$ = $3; }
//The ZEND_SEND_VAL branch is taken here
non_empty_function_call_parameter_list:
expr_without_variable { ....} //This branch is taken by mistake
| variable {..... } //Normal The situation


resulted in different OPCODEs being generated during compilation, which also led to the appearance of the problem.
Finally, I have explained the reason on this bug page of PHP. If you are interested, you can check out my bad English proficiency. Finally, thank you cici netizen for providing this interesting question.

The above introduces the analysis of the bug that causes the failure of reference parameter transfer in PHP error suppressor @, including the content. I hope it will be helpful to friends who are interested in PHP tutorials.

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn