]> granicus.if.org Git - php/commitdiff
Fix crash when exception is thrown during ROPE_END
authorNikita Popov <nikic@php.net>
Mon, 6 Jul 2015 18:12:07 +0000 (20:12 +0200)
committerNikita Popov <nikic@php.net>
Mon, 6 Jul 2015 18:15:45 +0000 (20:15 +0200)
The CHECK_EXCEPTION() was done at a point where the old opline is
still used, thus redirecting the write to the result var into
EX(call) instead.

Handling the exception in-place to avoid leaking result.

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

diff --git a/Zend/tests/exception_in_rope_end.phpt b/Zend/tests/exception_in_rope_end.phpt
new file mode 100644 (file)
index 0000000..3e6402c
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Exception during rope finalization
+--FILE--
+<?php
+
+set_error_handler(function() { throw new Exception; });
+
+try {
+    $b = "foo";
+    $str = "y$b$a";
+} catch (Exception $e) {
+    echo "Exception\n";
+}
+
+?>
+--EXPECT--
+Exception
index fb86a8d42a077490db7d892ac6283f802158b8e2..7bfec961cb55399c83288f3ee8703bb59017e203 100644 (file)
@@ -2859,7 +2859,12 @@ ZEND_VM_HANDLER(56, ZEND_ROPE_END, TMP, CONST|TMPVAR|CV)
                        }
                        rope[opline->extended_value] = _zval_get_string_func(var);
                        FREE_OP2();
-                       CHECK_EXCEPTION();
+                       if (UNEXPECTED(EG(exception))) {
+                               for (i = 0; i <= opline->extended_value; i++) {
+                                       zend_string_release(rope[i]);
+                               }
+                               HANDLE_EXCEPTION();
+                       }
                }
        }
        for (i = 0; i <= opline->extended_value; i++) {
index a948964e91bf0f068d6df4f462448ac37459e809..eebfc0f1e736c3cc30caf5d88859f3737627b991 100644 (file)
@@ -12999,7 +12999,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CONST_HANDLE
                        }
                        rope[opline->extended_value] = _zval_get_string_func(var);
 
-                       CHECK_EXCEPTION();
+                       if (UNEXPECTED(EG(exception))) {
+                               for (i = 0; i <= opline->extended_value; i++) {
+                                       zend_string_release(rope[i]);
+                               }
+                               HANDLE_EXCEPTION();
+                       }
                }
        }
        for (i = 0; i <= opline->extended_value; i++) {
@@ -14283,7 +14288,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(Z
                        }
                        rope[opline->extended_value] = _zval_get_string_func(var);
 
-                       CHECK_EXCEPTION();
+                       if (UNEXPECTED(EG(exception))) {
+                               for (i = 0; i <= opline->extended_value; i++) {
+                                       zend_string_release(rope[i]);
+                               }
+                               HANDLE_EXCEPTION();
+                       }
                }
        }
        for (i = 0; i <= opline->extended_value; i++) {
@@ -14796,7 +14806,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDL
                        }
                        rope[opline->extended_value] = _zval_get_string_func(var);
                        zval_ptr_dtor_nogc(free_op2);
-                       CHECK_EXCEPTION();
+                       if (UNEXPECTED(EG(exception))) {
+                               for (i = 0; i <= opline->extended_value; i++) {
+                                       zend_string_release(rope[i]);
+                               }
+                               HANDLE_EXCEPTION();
+                       }
                }
        }
        for (i = 0; i <= opline->extended_value; i++) {