]> granicus.if.org Git - php/commitdiff
Fixed bug #75786
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 9 Jan 2018 19:20:31 +0000 (20:20 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 9 Jan 2018 19:20:31 +0000 (20:20 +0100)
SEND_UNPACK on iterators was duplicating references in-place,
which effectively leaks the original value and causes an off-by-one
refcount on the duplicated value.

Replace this with a deref, as an actual duplication is not even
needed in this case.

NEWS
Zend/tests/bug75786.phpt [new file with mode: 0644]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index 67dfb464f96a300af84e1c651ea9ace599be6ef6..8414fcd79a9d35aae586b30bf6177c884170afee 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@ PHP                                                                        NEWS
 
 - Core:
   . Fixed bug #75679 (Path 260 character problem). (Anatol)
+  . Fixed bug #75786 (segfault when using spread operator on generator passed
+    by reference). (Nikita)
 
 - Opcache:
   . Fixed bug #75720 (File cache not populated after SHM runs full). (Dmitry)
diff --git a/Zend/tests/bug75786.phpt b/Zend/tests/bug75786.phpt
new file mode 100644 (file)
index 0000000..b93111b
--- /dev/null
@@ -0,0 +1,18 @@
+--TEST--
+Bug #75786: segfault when using spread operator on generator passed by reference
+--FILE--
+<?php
+
+function &gen($items) {
+    foreach ($items as $key => &$value) {
+        yield $key => $value;
+    }
+}
+
+var_dump(...gen(['a', 'b', 'c']));
+
+?>
+--EXPECT--
+string(1) "a"
+string(1) "b"
+string(1) "c"
index 8f68cdafd43cd194ea22d9b9bdb270420b0cdc5c..7dd70fa7091dff9a51fb46405ce446a59ca7ea21 100644 (file)
@@ -4647,11 +4647,8 @@ ZEND_VM_C_LABEL(send_again):
                                        );
                                }
 
-                               if (Z_ISREF_P(arg)) {
-                                       ZVAL_DUP(arg, Z_REFVAL_P(arg));
-                               } else {
-                                       if (Z_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
-                               }
+                               ZVAL_DEREF(arg);
+                               Z_TRY_ADDREF_P(arg);
 
                                zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1);
                                top = ZEND_CALL_ARG(EX(call), arg_num);
index a9735b1c5ade24a85e53792614d03f265b6efa6d..cb20546da9b0d94d850f31b6441851d6e67dd0e4 100644 (file)
@@ -1358,11 +1358,8 @@ send_again:
                                        );
                                }
 
-                               if (Z_ISREF_P(arg)) {
-                                       ZVAL_DUP(arg, Z_REFVAL_P(arg));
-                               } else {
-                                       if (Z_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
-                               }
+                               ZVAL_DEREF(arg);
+                               Z_TRY_ADDREF_P(arg);
 
                                zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1);
                                top = ZEND_CALL_ARG(EX(call), arg_num);