From fd30c59e041eb4ccaabb2099bb3be15a55e2988d Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 9 Jan 2018 20:20:31 +0100 Subject: [PATCH] Fixed bug #75786 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 | 2 ++ Zend/tests/bug75786.phpt | 18 ++++++++++++++++++ Zend/zend_vm_def.h | 7 ++----- Zend/zend_vm_execute.h | 7 ++----- 4 files changed, 24 insertions(+), 10 deletions(-) create mode 100644 Zend/tests/bug75786.phpt diff --git a/NEWS b/NEWS index 67dfb464f9..8414fcd79a 100644 --- 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 index 0000000000..b93111b9e3 --- /dev/null +++ b/Zend/tests/bug75786.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #75786: segfault when using spread operator on generator passed by reference +--FILE-- + &$value) { + yield $key => $value; + } +} + +var_dump(...gen(['a', 'b', 'c'])); + +?> +--EXPECT-- +string(1) "a" +string(1) "b" +string(1) "c" diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 8f68cdafd4..7dd70fa709 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -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); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index a9735b1c5a..cb20546da9 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -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); -- 2.40.0