]> granicus.if.org Git - php/commitdiff
Fixed bug #38808 ("maybe ref" issue for current() and others)
authorDmitry Stogov <dmitry@php.net>
Tue, 26 Sep 2006 10:30:51 +0000 (10:30 +0000)
committerDmitry Stogov <dmitry@php.net>
Tue, 26 Sep 2006 10:30:51 +0000 (10:30 +0000)
NEWS
Zend/tests/bug38808.phpt [new file with mode: 0755]
Zend/zend_compile.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index 0d3ac5d6feb7213b9317fb00e30c23a9d1f7f3af..bd52ebfee19d52874d63b40d9e09f8410031d903 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,7 @@ PHP                                                                        NEWS
 - Fixed bug #38891 (get_headers() do not work with curl-wrappers). (Ilia)
 - Fixed bug #38844 (curl_easy_strerror() is defined only since cURL 7.12.0).
   (Tony)
+- Fixed bug #38808 ("maybe ref" issue for current() and others). (Dmitry)
 - Fixed bug #38623 (leaks in a tricky code with switch() and exceptions).
   (Dmitry)
 - Fixed bug #38579 (include_once() may include the same file twice). (Dmitry)
diff --git a/Zend/tests/bug38808.phpt b/Zend/tests/bug38808.phpt
new file mode 100755 (executable)
index 0000000..0fc4bfe
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Bug #38808 ("maybe ref" issue for current() and others)
+--FILE--
+<?php
+$current = "current";
+$next = "next";
+
+$b = array(1=>'one', 2=>'two');
+$a =& $b;
+
+echo $current($a)."\n";
+$next($a);
+echo $current($a)."\n";
+?>
+--EXPECT--
+one
+two
\ No newline at end of file
index fb3bafa737f49aa18866ea5a74da14738358ee62..7d40c74c5fad38919b39baea90c495d8326dde20 100644 (file)
@@ -663,40 +663,22 @@ int zendlex(znode *zendlval TSRMLS_DC);
 #define ZEND_SEND_BY_REF     1
 #define ZEND_SEND_PREFER_REF 2
 
-/* Lost In Stupid Parentheses */
-#define ARG_SHOULD_BE_SENT_BY_REF(zf, arg_num)                                                                                 \
-       (                                                                                                                                                                       \
-               zf                                                                                                                                                              \
-               && ((zend_function *) zf)->common.arg_info                                                                              \
-               &&                                                                                                                                                              \
-               (                                                                                                                                                               \
-                       (                                                                                                                                                       \
-                               arg_num<=((zend_function *) zf)->common.num_args                                                \
-                               && ((zend_function *) zf)->common.arg_info[arg_num-1].pass_by_reference == ZEND_SEND_BY_REF \
-                       )                                                                                                                                                       \
-               ||      (                                                                                                                                                       \
-                               arg_num>((zend_function *) zf)->common.num_args                                                 \
-                               && ((zend_function *) zf)->common.pass_rest_by_reference == ZEND_SEND_BY_REF                            \
-                       )                                                                                                                                                       \
-               )                                                                                                                                                               \
-       )
-
-#define ARG_MAY_BE_SENT_BY_REF(zf, arg_num)                                                                                    \
-       (                                                                                                                                                                       \
-               zf                                                                                                                                                              \
-               && ((zend_function *) zf)->common.arg_info                                                                              \
-               &&                                                                                                                                                              \
-               (                                                                                                                                                               \
-                       (                                                                                                                                                       \
-                               arg_num<=((zend_function *) zf)->common.num_args                                                \
-                               && ((zend_function *) zf)->common.arg_info[arg_num-1].pass_by_reference == ZEND_SEND_PREFER_REF \
-                       )                                                                                                                                                       \
-               ||      (                                                                                                                                                       \
-                               arg_num>((zend_function *) zf)->common.num_args                                                 \
-                               && ((zend_function *) zf)->common.pass_rest_by_reference == ZEND_SEND_PREFER_REF                                \
-                       )                                                                                                                                                       \
-               )                                                                                                                                                               \
-       )
+#define ARG_SEND_TYPE(zf, arg_num)                                                                                             \
+       ((zf) ?                                                                     \
+        ((((zend_function*)(zf))->common.arg_info &&                               \
+          arg_num<=((zend_function*)(zf))->common.num_args) ?                      \
+         ((zend_function *)(zf))->common.arg_info[arg_num-1].pass_by_reference :   \
+         ((zend_function *)(zf))->common.pass_rest_by_reference) :                 \
+        ZEND_SEND_BY_VAL)      
+
+#define ARG_MUST_BE_SENT_BY_REF(zf, arg_num) \
+       (ARG_SEND_TYPE(zf, arg_num) == ZEND_SEND_BY_REF)
+
+#define ARG_SHOULD_BE_SENT_BY_REF(zf, arg_num) \
+       (ARG_SEND_TYPE(zf, arg_num) & (ZEND_SEND_BY_REF|ZEND_SEND_PREFER_REF))
+
+#define ARG_MAY_BE_SENT_BY_REF(zf, arg_num) \
+       (ARG_SEND_TYPE(zf, arg_num) == ZEND_SEND_PREFER_REF)
 
 #define ZEND_RETURN_VAL 0
 #define ZEND_RETURN_REF 1
index 13204e692c50db02c322ae677914cee991316c91..c1626bd1991738cad4da676c33b33f4dcf9154a0 100644 (file)
@@ -2191,7 +2191,7 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP|VAR|CV, ANY)
 {
        zend_op *opline = EX(opline);
        if (opline->extended_value==ZEND_DO_FCALL_BY_NAME
-               && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
+               && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
                        zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.u.opline_num);
        }
        {
index 277cd3cf3767946065b75b391f7c260258bbacb7..725794659f88ab1d97f6c8b17c52eb01296419bd 100644 (file)
@@ -1794,7 +1794,7 @@ static int ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
        if (opline->extended_value==ZEND_DO_FCALL_BY_NAME
-               && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
+               && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
                        zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.u.opline_num);
        }
        {
@@ -4320,7 +4320,7 @@ static int ZEND_SEND_VAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
        if (opline->extended_value==ZEND_DO_FCALL_BY_NAME
-               && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
+               && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
                        zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.u.opline_num);
        }
        {
@@ -7338,7 +7338,7 @@ static int ZEND_SEND_VAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
        if (opline->extended_value==ZEND_DO_FCALL_BY_NAME
-               && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
+               && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
                        zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.u.opline_num);
        }
        {
@@ -19377,7 +19377,7 @@ static int ZEND_SEND_VAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
        if (opline->extended_value==ZEND_DO_FCALL_BY_NAME
-               && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
+               && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
                        zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.u.opline_num);
        }
        {