From c3272ab020f07bff10b44a57c91a30339b52a883 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 26 Sep 2006 10:30:51 +0000 Subject: [PATCH] Fixed bug #38808 ("maybe ref" issue for current() and others) --- NEWS | 1 + Zend/tests/bug38808.phpt | 17 ++++++++++++++ Zend/zend_compile.h | 50 +++++++++++++--------------------------- Zend/zend_vm_def.h | 2 +- Zend/zend_vm_execute.h | 8 +++---- 5 files changed, 39 insertions(+), 39 deletions(-) create mode 100755 Zend/tests/bug38808.phpt diff --git a/NEWS b/NEWS index 0d3ac5d6fe..bd52ebfee1 100644 --- 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 index 0000000000..0fc4bfecdc --- /dev/null +++ b/Zend/tests/bug38808.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #38808 ("maybe ref" issue for current() and others) +--FILE-- +'one', 2=>'two'); +$a =& $b; + +echo $current($a)."\n"; +$next($a); +echo $current($a)."\n"; +?> +--EXPECT-- +one +two \ No newline at end of file diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index fb3bafa737..7d40c74c5f 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -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 diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 13204e692c..c1626bd199 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -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); } { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 277cd3cf37..725794659f 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -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); } { -- 2.40.0