ソースを参照

Throw exception if __construct is not public

Stefan Siegl 12 年 前
コミット
5987d5d3da
2 ファイル変更105 行追加3 行削除
  1. 96 0
      tests/js-construct-protected-ctor.phpt
  2. 9 3
      v8js_convert.cc

+ 96 - 0
tests/js-construct-protected-ctor.phpt

@@ -0,0 +1,96 @@
+--TEST--
+Test V8::executeString() : Test PHP object construction controlled by JavaScript (protected ctor)
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--FILE--
+<?php
+$v8 = new V8Js();
+
+class Greeter {
+	protected $_name = null;
+
+	protected function __construct($name) {
+		echo "ctor called (php)\n";
+		$this->_name = $name;
+	}
+
+	static function getInstance($name) {
+		return new Greeter($name);
+	}
+
+	function sayHello() {
+		echo "Hello ".$this->_name."\n";
+	}
+}
+
+$v8->greeter = Greeter::getInstance("John");
+
+try {
+	$v8->executeString('
+		PHP.greeter.sayHello();
+
+		var ngGreeter = new PHP.greeter.constructor("Ringo");
+		ngGreeter.sayHello();
+	', 'ctor-test');
+} catch(V8JsScriptException $e) {
+	echo "caught js exception\n";
+	var_dump($e);
+}
+?>
+===EOF===
+--EXPECTF--
+ctor called (php)
+Hello John
+caught js exception
+object(V8JsScriptException)#3 (11) {
+  ["message":protected]=>
+  string(56) "ctor-test:4: Call to protected __construct() not allowed"
+  ["string":"Exception":private]=>
+  string(0) ""
+  ["code":protected]=>
+  int(0)
+  ["file":protected]=>
+  string(%d) "%s"
+  ["line":protected]=>
+  int(29)
+  ["trace":"Exception":private]=>
+  array(1) {
+    [0]=>
+    array(6) {
+      ["file"]=>
+      string(%d) "%s"
+      ["line"]=>
+      int(29)
+      ["function"]=>
+      string(13) "executeString"
+      ["class"]=>
+      string(4) "V8Js"
+      ["type"]=>
+      string(2) "->"
+      ["args"]=>
+      array(2) {
+        [0]=>
+        string(109) "
+		PHP.greeter.sayHello();
+
+		var ngGreeter = new PHP.greeter.constructor("Ringo");
+		ngGreeter.sayHello();
+	"
+        [1]=>
+        string(9) "ctor-test"
+      }
+    }
+  }
+  ["previous":"Exception":private]=>
+  NULL
+  ["JsFileName":protected]=>
+  string(9) "ctor-test"
+  ["JsLineNumber":protected]=>
+  int(4)
+  ["JsSourceLine":protected]=>
+  string(55) "		var ngGreeter = new PHP.greeter.constructor("Ringo");"
+  ["JsTrace":protected]=>
+  NULL
+}
+===EOF===
+

+ 9 - 3
v8js_convert.cc

@@ -172,14 +172,20 @@ static void php_v8js_construct_callback(const v8::FunctionCallbackInfo<v8::Value
 	} else {
 		// Object created from JavaScript context.  Need to create PHP object first.
 		zend_class_entry *ce = static_cast<zend_class_entry *>(v8::External::Cast(*info.Data())->Value());
+		zend_function *ctor_ptr = ce->constructor;
+
+		// Check access on __construct function, if any
+		if (ctor_ptr != NULL && (ctor_ptr->common.fn_flags & ZEND_ACC_PUBLIC) == 0) {
+			info.GetReturnValue().Set(v8::ThrowException(v8::String::New("Call to protected __construct() not allowed")));
+			return;
+		}
 
 		MAKE_STD_ZVAL(value);
 		object_init_ex(value, ce TSRMLS_CC);
 
 		// Call __construct function
-		if(ce->constructor != NULL) {
-			zend_function *method_ptr = ce->constructor;
-			php_v8js_call_php_func(value, ce, method_ptr, isolate, info);
+		if (ctor_ptr != NULL) {
+			php_v8js_call_php_func(value, ce, ctor_ptr, isolate, info);
 		}
 	}