Commit:    d53f1bf8ab326a6fd3596a5f265d04bf49de74fe
Author:    Nikita Popov <ni...@php.net>         Tue, 18 Dec 2012 21:36:48 +0100
Parents:   19f8bba10d3580308bfe19234a5a26a4f71ecd9a
Branches:  PHP-5.5 master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=d53f1bf8ab326a6fd3596a5f265d04bf49de74fe

Log:
Fix leak when generator ignores sent value

When the return value of yield wasn't used it was leaked.

This is fixed by using a TMP_VAR return value instead of VAR. TMP_VARs are
automatically freed when they aren't used.

Changed paths:
  A  Zend/tests/generators/ignored_send_leak.phpt
  M  Zend/zend_compile.c
  M  Zend/zend_generators.c
  M  Zend/zend_vm_def.h
  M  Zend/zend_vm_execute.h

diff --git a/Zend/tests/generators/ignored_send_leak.phpt 
b/Zend/tests/generators/ignored_send_leak.phpt
new file mode 100644
index 0000000..352ba40
--- /dev/null
+++ b/Zend/tests/generators/ignored_send_leak.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Ignoring a sent value shouldn't leak memory
+--FILE--
+<?php
+
+function gen() {
+    yield;
+}
+
+$gen = gen();
+$gen->send(NULL);
+
+echo "DONE";
+
+?>
+--EXPECT--
+DONE
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index ac3e633..d28b65a 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -2736,7 +2736,7 @@ void zend_do_yield(znode *result, znode *value, const 
znode *key, zend_bool is_v
                SET_UNUSED(opline->op2);
        }
 
-       opline->result_type = IS_VAR;
+       opline->result_type = IS_TMP_VAR;
        opline->result.var = get_temporary_variable(CG(active_op_array));
        GET_NODE(result, opline->result);
 }
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c
index 9eae2c7..d4254e0 100644
--- a/Zend/zend_generators.c
+++ b/Zend/zend_generators.c
@@ -319,7 +319,7 @@ static void zend_generator_clone_storage(zend_generator 
*orig, zend_generator **
                if (orig->send_target) {
                        size_t offset = (char *) orig->send_target - (char 
*)execute_data;
                        clone->send_target = EX_TMP_VAR(clone->execute_data, 
offset);
-                       Z_ADDREF_P(clone->send_target->var.ptr);
+                       zval_copy_ctor(&clone->send_target->tmp_var);
                }
 
                if (execute_data->current_this) {
@@ -641,13 +641,8 @@ ZEND_METHOD(Generator, send)
                return;
        }
 
-       /* The sent value was initialized to NULL, so dtor that */
-       zval_ptr_dtor(&generator->send_target->var.ptr);
-
-       /* Set new sent value */
-       Z_ADDREF_P(value);
-       generator->send_target->var.ptr = value;
-       generator->send_target->var.ptr_ptr = &value;
+       /* Put sent value into the TMP_VAR slot */
+       MAKE_COPY_ZVAL(&value, &generator->send_target->tmp_var);
 
        zend_generator_resume(generator TSRMLS_CC);
 
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index f7b10a2..c933a48 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -5371,8 +5371,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, 
CONST|TMP|VAR|CV|UNUSE
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index c077d5d..dab0df3 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -4183,8 +4183,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -4879,8 +4878,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -5901,8 +5899,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -6616,8 +6613,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -7371,8 +7367,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -9417,8 +9412,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -10113,8 +10107,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -11135,8 +11128,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -11714,8 +11706,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -12407,8 +12398,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -16315,8 +16305,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -18403,8 +18392,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -20872,8 +20860,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -22014,8 +22001,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -24151,8 +24137,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -25642,8 +25627,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -26957,8 +26941,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -28273,8 +28256,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -28696,8 +28678,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -30008,8 +29989,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -33513,8 +33493,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -35468,8 +35447,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -37803,8 +37781,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -38802,8 +38779,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
@@ -40805,8 +40781,7 @@ static int ZEND_FASTCALL  
ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
        generator->send_target = &EX_T(opline->result.var);
 
        /* Initialize the sent value to NULL */
-       Z_ADDREF(EG(uninitialized_zval));
-       AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+       EX_T(opline->result.var).tmp_var = EG(uninitialized_zval);
 
        /* We increment to the next op, so we are at the correct position when 
the
         * generator is resumed. */
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to