]> granicus.if.org Git - php/commitdiff
Fixed bug #47165 (Possible memory corruption when passing return value by reference)
authorDmitry Stogov <dmitry@php.net>
Wed, 21 Jan 2009 10:15:49 +0000 (10:15 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 21 Jan 2009 10:15:49 +0000 (10:15 +0000)
NEWS
Zend/tests/bug47165.phpt [new file with mode: 0644]
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index 9113cc6ba6a24041e60734158ec9056567a75a5a..844947aec249493d5f7b5ecb6473956716550533 100644 (file)
--- 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 (file)
index 0000000..2cf648d
--- /dev/null
@@ -0,0 +1,18 @@
+--TEST--
+Bug #47165 (Possible memory corruption when passing return value by reference)
+--FILE--
+<?php
+class Foo {
+       var $bar = array();
+
+       static function bar() {
+               static $instance = null;
+               $instance = new Foo();
+               return $instance->bar;
+       }
+}
+extract(Foo::bar());
+echo "ok\n";
+?>
+--EXPECT--
+ok
index c64a882378d28dc7b7ba260a114b372099d5c55b..2634693686361fccf026f6a73d88804e39538368 100644 (file)
@@ -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;
                }
index 8d5b03951ecd57280a67023f6a315aaa1359a662..121db7dd78bb631d989e9b0cfdf34448cbff2591 100644 (file)
@@ -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
index 2bab65770df23a84182cc7c47fa0c9479cb5f1bd..c734f24900498176e14078d7f964f68a03c55b7d 100644 (file)
@@ -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()) {
index b28a4079a9da21c2800cb886522c483e0680b890..4ae2cffb3e9add330c3f86dd2b448185dcee4bd9 100644 (file)
@@ -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) {