From: Dmitry Stogov Date: Wed, 21 Jan 2009 10:15:49 +0000 (+0000) Subject: Fixed bug #47165 (Possible memory corruption when passing return value by reference) X-Git-Tag: php-5.2.9RC1~72 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=85489ac01ae439c83487e0046df9c786e0ffa14b;p=php Fixed bug #47165 (Possible memory corruption when passing return value by reference) --- diff --git a/NEWS b/NEWS index 9113cc6ba6..844947aec2 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,8 @@ PHP NEWS - Fixed bug in xml_error_string() which resulted in messages being off by one. (Scott) +- Fixed bug #47165 (Possible memory corruption when passing return value by + reference). (Dmitry) - Fixed bug #47152 (gzseek/fseek using SEEK_END produces strange results). (Felipe) - Fixed bug #47131 (SOAP Extension ignores "user_agent" ini setting). (Ilia) diff --git a/Zend/tests/bug47165.phpt b/Zend/tests/bug47165.phpt new file mode 100644 index 0000000000..2cf648d855 --- /dev/null +++ b/Zend/tests/bug47165.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #47165 (Possible memory corruption when passing return value by reference) +--FILE-- +bar; + } +} +extract(Foo::bar()); +echo "ok\n"; +?> +--EXPECT-- +ok diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index c64a882378..2634693686 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1607,8 +1607,17 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) if (function_ptr) { if (ARG_MAY_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) { - op = (param->op_type & (IS_VAR|IS_CV))?ZEND_SEND_REF:ZEND_SEND_VAL; - send_by_reference = 0; + if (param->op_type & (IS_VAR|IS_CV)) { + send_by_reference = 1; + if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) { + /* Method call */ + op = ZEND_SEND_VAR_NO_REF; + send_function = ZEND_ARG_SEND_FUNCTION | ZEND_ARG_SEND_SILENT; + } + } else { + op = ZEND_SEND_VAL; + send_by_reference = 0; + } } else { send_by_reference = ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset) ? ZEND_ARG_SEND_BY_REF : 0; } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 8d5b03951e..121db7dd78 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -659,6 +659,7 @@ int zendlex(znode *zendlval TSRMLS_DC); #define ZEND_ARG_SEND_BY_REF (1<<0) #define ZEND_ARG_COMPILE_TIME_BOUND (1<<1) #define ZEND_ARG_SEND_FUNCTION (1<<2) +#define ZEND_ARG_SEND_SILENT (1<<3) #define ZEND_SEND_BY_VAL 0 #define ZEND_SEND_BY_REF 1 diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 2bab65770d..c734f24900 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2331,7 +2331,9 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY) } else { zval *valptr; - zend_error(E_STRICT, "Only variables should be passed by reference"); + if (!(opline->extended_value & ZEND_ARG_SEND_SILENT)) { + zend_error(E_STRICT, "Only variables should be passed by reference"); + } ALLOC_ZVAL(valptr); INIT_PZVAL_COPY(valptr, varptr); if (!IS_OP1_TMP_FREE()) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index b28a4079a9..4ae2cffb3e 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -7554,7 +7554,9 @@ static int ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { zval *valptr; - zend_error(E_STRICT, "Only variables should be passed by reference"); + if (!(opline->extended_value & ZEND_ARG_SEND_SILENT)) { + zend_error(E_STRICT, "Only variables should be passed by reference"); + } ALLOC_ZVAL(valptr); INIT_PZVAL_COPY(valptr, varptr); if (!0) { @@ -19876,7 +19878,9 @@ static int ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { zval *valptr; - zend_error(E_STRICT, "Only variables should be passed by reference"); + if (!(opline->extended_value & ZEND_ARG_SEND_SILENT)) { + zend_error(E_STRICT, "Only variables should be passed by reference"); + } ALLOC_ZVAL(valptr); INIT_PZVAL_COPY(valptr, varptr); if (!0) {