]> granicus.if.org Git - php/commitdiff
Fixed iter leak on by-ref foreach over const/tmp array
authorNikita Popov <nikic@php.net>
Thu, 17 Dec 2015 22:21:48 +0000 (23:21 +0100)
committerNikita Popov <nikic@php.net>
Thu, 17 Dec 2015 22:21:48 +0000 (23:21 +0100)
FE_FREE does not unregister the iter for plain arrays. So always
wrap into a REF wrapper, even if not strictly necessary, in
RESET_RW. Alternatively we could use a flag to distinguish plain
positions and interators.

Also added a check for leaked iterators in shutdown_executor.

Zend/zend_execute_API.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index fdffed34b275775084eeaf943a12c992edac2e0c..6eafeb75500b87877a387d066dbfb928c2bcefe3 100644 (file)
@@ -397,6 +397,12 @@ void shutdown_executor(void) /* {{{ */
 
        zend_shutdown_fpu();
 
+#ifdef ZEND_DEBUG
+       if (EG(ht_iterators_used)) {
+               zend_error(E_WARNING, "Leaked %" PRIu32 " hashtable iterators", EG(ht_iterators_used));
+       }
+#endif
+
        EG(ht_iterators_used) = 0;
        if (EG(ht_iterators) != EG(ht_iterators_slots)) {
                efree(EG(ht_iterators));
index 0e555f5f83a8853b8134564fe600fab0104f455e..f02a0e824825d6abf4c8f4f501897a419ef06da7 100644 (file)
@@ -5854,8 +5854,9 @@ ZEND_VM_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, ANY)
                        Z_ADDREF_P(array_ref);
                        ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
                } else {
-                       array_ptr = EX_VAR(opline->result.var);
-                       ZVAL_COPY_VALUE(array_ptr, array_ref);
+                       array_ref = EX_VAR(opline->result.var);
+                       ZVAL_NEW_REF(array_ref, array_ptr);
+                       array_ptr = Z_REFVAL_P(array_ref);
                }
                if (OP1_TYPE == IS_CONST) {
                        zval_copy_ctor_func(array_ptr);
index 8ef0c4dbbfc415e8dadbe0d65b5278def13a6765..52a122c94a20d7f0b7f8da4da738d2b88dfd125c 100644 (file)
@@ -3833,8 +3833,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER
                        Z_ADDREF_P(array_ref);
                        ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
                } else {
-                       array_ptr = EX_VAR(opline->result.var);
-                       ZVAL_COPY_VALUE(array_ptr, array_ref);
+                       array_ref = EX_VAR(opline->result.var);
+                       ZVAL_NEW_REF(array_ref, array_ptr);
+                       array_ptr = Z_REFVAL_P(array_ref);
                }
                if (IS_CONST == IS_CONST) {
                        zval_copy_ctor_func(array_ptr);
@@ -12182,8 +12183,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(Z
                        Z_ADDREF_P(array_ref);
                        ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
                } else {
-                       array_ptr = EX_VAR(opline->result.var);
-                       ZVAL_COPY_VALUE(array_ptr, array_ref);
+                       array_ref = EX_VAR(opline->result.var);
+                       ZVAL_NEW_REF(array_ref, array_ptr);
+                       array_ptr = Z_REFVAL_P(array_ref);
                }
                if (IS_TMP_VAR == IS_CONST) {
                        zval_copy_ctor_func(array_ptr);
@@ -15627,8 +15629,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(Z
                        Z_ADDREF_P(array_ref);
                        ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
                } else {
-                       array_ptr = EX_VAR(opline->result.var);
-                       ZVAL_COPY_VALUE(array_ptr, array_ref);
+                       array_ref = EX_VAR(opline->result.var);
+                       ZVAL_NEW_REF(array_ref, array_ptr);
+                       array_ptr = Z_REFVAL_P(array_ref);
                }
                if (IS_VAR == IS_CONST) {
                        zval_copy_ctor_func(array_ptr);
@@ -29312,8 +29315,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZE
                        Z_ADDREF_P(array_ref);
                        ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
                } else {
-                       array_ptr = EX_VAR(opline->result.var);
-                       ZVAL_COPY_VALUE(array_ptr, array_ref);
+                       array_ref = EX_VAR(opline->result.var);
+                       ZVAL_NEW_REF(array_ref, array_ptr);
+                       array_ptr = Z_REFVAL_P(array_ref);
                }
                if (IS_CV == IS_CONST) {
                        zval_copy_ctor_func(array_ptr);