]> granicus.if.org Git - php/commitdiff
Fixed bug #77263 (Segfault when using 2 RecursiveFilterIterator)
authorDmitry Stogov <dmitry@zend.com>
Mon, 14 Jan 2019 10:18:28 +0000 (13:18 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 14 Jan 2019 10:18:28 +0000 (13:18 +0300)
NEWS
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/spl/tests/bug77263.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 951154e5de85c391ea21ed1e8cf830124e0a1330..9d85fcd8d108ff49512eb39b8e1068f2763c4f4c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,7 @@ PHP                                                                        NEWS
   . Fixed bug #77339 (__callStatic may get incorrect arguments). (Dmitry)
   . Fixed bug #77317 (__DIR__, __FILE__, realpath() reveal physical path for
     subst virtual drive). (Anatol)
+  . Fixed bug #77263 (Segfault when using 2 RecursiveFilterIterator). (Dmitry)
 
 - Fileinfo:
   . Fixed bug #77346 (webm files incorrectly detected as
index a49baa5a9bc1294b8c12b938ce5280842f7c1b44..5071be0fb17bea5939246d361fa34a32514e8993 100644 (file)
@@ -3099,6 +3099,10 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
                    EXPECTED(obj == orig_obj)) {
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
+               if ((OP1_TYPE & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
+                       /* Reset "object" to trigger reference counting */
+                       object = NULL;
+               }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
                        init_func_run_time_cache(&fbc->op_array);
                }
index 49bc2c0de77e630f2a7dea7575c5ae15c391586f..2ed807f1ac5e9d29e561a5eeadc037571a7d0b1c 100644 (file)
@@ -5148,6 +5148,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
                    EXPECTED(obj == orig_obj)) {
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
+               if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
+                       /* Reset "object" to trigger reference counting */
+                       object = NULL;
+               }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
                        init_func_run_time_cache(&fbc->op_array);
                }
@@ -7325,6 +7329,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
                    EXPECTED(obj == orig_obj)) {
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
+               if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
+                       /* Reset "object" to trigger reference counting */
+                       object = NULL;
+               }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
                        init_func_run_time_cache(&fbc->op_array);
                }
@@ -10421,6 +10429,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_
                    EXPECTED(obj == orig_obj)) {
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
+               if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
+                       /* Reset "object" to trigger reference counting */
+                       object = NULL;
+               }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
                        init_func_run_time_cache(&fbc->op_array);
                }
@@ -14149,6 +14161,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
                    EXPECTED(obj == orig_obj)) {
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
+               if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
+                       /* Reset "object" to trigger reference counting */
+                       object = NULL;
+               }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
                        init_func_run_time_cache(&fbc->op_array);
                }
@@ -15759,6 +15775,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T
                    EXPECTED(obj == orig_obj)) {
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
+               if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
+                       /* Reset "object" to trigger reference counting */
+                       object = NULL;
+               }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
                        init_func_run_time_cache(&fbc->op_array);
                }
@@ -17636,6 +17656,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
                    EXPECTED(obj == orig_obj)) {
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
+               if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
+                       /* Reset "object" to trigger reference counting */
+                       object = NULL;
+               }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
                        init_func_run_time_cache(&fbc->op_array);
                }
@@ -32081,6 +32105,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S
                    EXPECTED(obj == orig_obj)) {
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
+               if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
+                       /* Reset "object" to trigger reference counting */
+                       object = NULL;
+               }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
                        init_func_run_time_cache(&fbc->op_array);
                }
@@ -33812,6 +33840,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T
                    EXPECTED(obj == orig_obj)) {
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
+               if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
+                       /* Reset "object" to trigger reference counting */
+                       object = NULL;
+               }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
                        init_func_run_time_cache(&fbc->op_array);
                }
@@ -36187,6 +36219,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
                    EXPECTED(obj == orig_obj)) {
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
+               if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
+                       /* Reset "object" to trigger reference counting */
+                       object = NULL;
+               }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
                        init_func_run_time_cache(&fbc->op_array);
                }
@@ -41208,6 +41244,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S
                    EXPECTED(obj == orig_obj)) {
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
+               if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
+                       /* Reset "object" to trigger reference counting */
+                       object = NULL;
+               }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
                        init_func_run_time_cache(&fbc->op_array);
                }
@@ -44971,6 +45011,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA
                    EXPECTED(obj == orig_obj)) {
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
+               if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
+                       /* Reset "object" to trigger reference counting */
+                       object = NULL;
+               }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
                        init_func_run_time_cache(&fbc->op_array);
                }
@@ -50769,6 +50813,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA
                    EXPECTED(obj == orig_obj)) {
                        CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
                }
+               if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
+                       /* Reset "object" to trigger reference counting */
+                       object = NULL;
+               }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
                        init_func_run_time_cache(&fbc->op_array);
                }
diff --git a/ext/spl/tests/bug77263.phpt b/ext/spl/tests/bug77263.phpt
new file mode 100644 (file)
index 0000000..ddd5fba
--- /dev/null
@@ -0,0 +1,40 @@
+--TEST--
+Bug #77263 (Segfault when using 2 RecursiveFilterIterator)
+--FILE--
+<?php
+$dir = __DIR__ . '/bug77263';
+mkdir($dir);
+mkdir("$dir/subdir");
+touch("$dir/file1");
+touch("$dir/subdir/file2");
+
+class Filter1 extends RecursiveFilterIterator {
+    public function accept() { return $this->getInnerIterator()->getSubPathname() != ''; }
+}
+
+class Filter2 extends RecursiveFilterIterator {
+    public function accept() { return $this->getInnerIterator()->getSubPathname() != ' '; }
+}
+
+$iterator = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS );
+
+$iterator = new Filter1( $iterator );
+
+$iterator = new Filter2( $iterator );
+
+$iterator = new RecursiveIteratorIterator( $iterator, RecursiveIteratorIterator::LEAVES_ONLY, RecursiveIteratorIterator::CATCH_GET_CHILD );
+
+foreach ( $iterator as $item ) {
+}
+?>
+OK
+--CLEAN--
+<?php
+$dir = __DIR__ . '/bug77263';
+unlink("$dir/file1");
+unlink("$dir/subdir/file2");
+rmdir("$dir/subdir");
+rmdir($dir);
+?>
+--EXPECT--
+OK