Переглянути джерело

Handle fatal errors even if executeString is used recursively

Stefan Siegl 11 роки тому
батько
коміт
6f31840daf
2 змінених файлів з 51 додано та 8 видалено
  1. 38 0
      tests/fatal_error_recursive.phpt
  2. 13 8
      v8js_convert.cc

+ 38 - 0
tests/fatal_error_recursive.phpt

@@ -0,0 +1,38 @@
+--TEST--
+Test V8::executeString() : Fatal Error with recursive executeString calls
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--FILE--
+<?php
+
+$js = new V8Js();
+
+$js->baz = function() {
+	$bar = null;
+	$bar->bar();
+};
+
+$js->bar = function() {
+	global $js;
+	$js->executeString("PHP.baz();");
+};
+
+$js->foo = function() {
+	global $js;
+	$js->executeString("PHP.bar();");
+};
+
+$js->nofail = function() {
+	echo "foo\n";
+};
+
+$js->executeString("PHP.nofail();");
+$js->executeString("PHP.nofail(); PHP.foo();");
+
+?>
+===EOF===
+--EXPECTF--
+foo
+foo
+
+Fatal error: Call to a member function bar() on a non-object in %s/fatal_error_recursive.php on line 7

+ 13 - 8
v8js_convert.cc

@@ -149,22 +149,27 @@ static void php_v8js_call_php_func(zval *value, zend_class_entry *ce, zend_funct
 		fcc.object_ptr = value;
 
 		jmp_buf env;
-		int val;
+		int val = 0;
 
 		void (*old_error_handler)(int, const char *, const uint, const char*, va_list);
-		old_error_handler = zend_error_cb;
-		zend_error_cb = php_v8js_error_handler;
 
-		val = setjmp (env);
-		V8JSG(unwind_env) = &env;
+		if (V8JSG(unwind_env) == NULL) {
+			old_error_handler = zend_error_cb;
+			zend_error_cb = php_v8js_error_handler;
 
-		if (val) {
-			zend_error_cb = old_error_handler;
+			val = setjmp (env);
+			V8JSG(unwind_env) = &env;
 		}
-		else {
+
+		if (!val) {
 			/* Call the method */
 			zend_call_function(&fci, &fcc TSRMLS_CC);
 		}
+
+		if (old_error_handler != NULL) {
+			zend_error_cb = old_error_handler;
+			V8JSG(unwind_env) = NULL;
+		}
 	}
 
 	isolate->Enter();