0
0
mirror of https://github.com/phpv8/v8js.git synced 2024-11-14 16:28:41 +00:00

Merge pull request #253 from stesie/issue-250

Fix refcounting, use zval_ptr_dtor, closes #250
This commit is contained in:
Stefan Siegl 2016-08-12 15:40:47 +02:00 committed by GitHub
commit 12d22b569e
8 changed files with 146 additions and 27 deletions

75
tests/issue_250_001.phpt Normal file
View File

@ -0,0 +1,75 @@
--TEST--
Test V8::executeString() : Issue #250 (early free of array)
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
class TestObject {
private $data = [];
private $meta = [];
public function setTitle($title) {
$this->a->b->title = $title;
}
public function getData() {
return $this->data;
}
public function getMeta() {
return $this->meta;
}
public function setData($data=[]) {
$this->data = $data;
}
public function setMeta($meta) {
return;
}
}
$v8 = new V8Js("server");
$code = <<< EOT
var v1 = server.response.getData();
var v2 = server.response.getMeta();
server.response.setData({});
server.response.setTitle("ouch");
server.response.setMeta({});
EOT;
$response = new TestObject();
$v8->response = $response;
try {
$result = $v8->executeString($code);
var_dump($v8->response);
} catch (V8JsException $e) {
var_dump($e);
}
?>
===EOF===
--EXPECTF--
Warning: Creating default object from empty value in %s%eissue_250_001.php on line 9
object(TestObject)#%d (3) {
["data":"TestObject":private]=>
object(V8Object)#%d (0) {
}
["meta":"TestObject":private]=>
array(0) {
}
["a"]=>
object(stdClass)#%d (1) {
["b"]=>
object(stdClass)#%d (1) {
["title"]=>
string(4) "ouch"
}
}
}
===EOF===

44
tests/issue_250_002.phpt Normal file
View File

@ -0,0 +1,44 @@
--TEST--
Test V8::executeString() : Issue #250 (early free of array)
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
class TestObject {
var $data;
public function setData($data) {
$this->data = $data;
}
public function getData() {
return $this->data;
}
}
$v8 = new V8Js("server");
$code = <<< EOT
server.response.setData({"new": true});
EOT;
$v8->response = new TestObject();
try {
$result = $v8->executeString($code, null, \V8Js::FLAG_FORCE_ARRAY | \V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS);
var_dump($v8->response->getData());
} catch (V8JsException $e) {
var_dump($e);
}
?>
===EOF===
--EXPECT--
array(1) {
["new"]=>
bool(true)
}
===EOF===

View File

@ -70,7 +70,7 @@ void v8js_array_access_getter(uint32_t index, const v8::PropertyCallbackInfo<v8:
zval php_value = v8js_array_access_dispatch(object, "offsetGet", 1, index, zvalue TSRMLS_CC); zval php_value = v8js_array_access_dispatch(object, "offsetGet", 1, index, zvalue TSRMLS_CC);
v8::Local<v8::Value> ret_value = zval_to_v8js(&php_value, isolate TSRMLS_CC); v8::Local<v8::Value> ret_value = zval_to_v8js(&php_value, isolate TSRMLS_CC);
zval_dtor(&php_value); zval_ptr_dtor(&php_value);
info.GetReturnValue().Set(ret_value); info.GetReturnValue().Set(ret_value);
} }
@ -95,7 +95,7 @@ void v8js_array_access_setter(uint32_t index, v8::Local<v8::Value> value,
} }
zval php_value = v8js_array_access_dispatch(object, "offsetSet", 2, index, zvalue TSRMLS_CC); zval php_value = v8js_array_access_dispatch(object, "offsetSet", 2, index, zvalue TSRMLS_CC);
zval_dtor(&php_value); zval_ptr_dtor(&php_value);
/* simply pass back the value to tell we intercepted the call /* simply pass back the value to tell we intercepted the call
* as the offsetSet function returns void. */ * as the offsetSet function returns void. */
@ -103,7 +103,7 @@ void v8js_array_access_setter(uint32_t index, v8::Local<v8::Value> value,
/* if PHP wanted to hold on to this value, zend_call_function would /* if PHP wanted to hold on to this value, zend_call_function would
* have bumped the refcount. */ * have bumped the refcount. */
zval_dtor(&zvalue); zval_ptr_dtor(&zvalue);
} }
/* }}} */ /* }}} */
@ -117,7 +117,7 @@ static int v8js_array_access_get_count_result(zend_object *object TSRMLS_DC) /*
if(Z_TYPE(php_value) != IS_LONG) { if(Z_TYPE(php_value) != IS_LONG) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Non-numeric return value from count() method"); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Non-numeric return value from count() method");
zval_dtor(&php_value); zval_ptr_dtor(&php_value);
return 0; return 0;
} }
@ -135,7 +135,7 @@ static bool v8js_array_access_isset_p(zend_object *object, int index TSRMLS_DC)
if(Z_TYPE(php_value) != IS_TRUE && Z_TYPE(php_value) != IS_FALSE) { if(Z_TYPE(php_value) != IS_TRUE && Z_TYPE(php_value) != IS_FALSE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Non-boolean return value from offsetExists() method"); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Non-boolean return value from offsetExists() method");
zval_dtor(&php_value); zval_ptr_dtor(&php_value);
return false; return false;
} }

View File

@ -88,9 +88,9 @@ static void v8js_free_storage(zend_object *object TSRMLS_DC) /* {{{ */
zend_object_std_dtor(&c->std TSRMLS_CC); zend_object_std_dtor(&c->std TSRMLS_CC);
zval_dtor(&c->pending_exception); zval_ptr_dtor(&c->pending_exception);
zval_dtor(&c->module_normaliser); zval_ptr_dtor(&c->module_normaliser);
zval_dtor(&c->module_loader); zval_ptr_dtor(&c->module_loader);
/* Delete PHP global object from JavaScript */ /* Delete PHP global object from JavaScript */
if (!c->context.IsEmpty()) { if (!c->context.IsEmpty()) {
@ -150,7 +150,7 @@ static void v8js_free_storage(zend_object *object TSRMLS_DC) /* {{{ */
zend_object *object = it->first; zend_object *object = it->first;
zval value; zval value;
ZVAL_OBJ(&value, object); ZVAL_OBJ(&value, object);
zval_dtor(&value); zval_ptr_dtor(&value);
c->isolate->AdjustAmountOfExternalAllocatedMemory(-c->average_object_size); c->isolate->AdjustAmountOfExternalAllocatedMemory(-c->average_object_size);
it->second.Reset(); it->second.Reset();
} }
@ -200,7 +200,7 @@ static void v8js_free_storage(zend_object *object TSRMLS_DC) /* {{{ */
c->modules_stack.~vector(); c->modules_stack.~vector();
c->modules_base.~vector(); c->modules_base.~vector();
zval_dtor(&c->zval_snapshot_blob); zval_ptr_dtor(&c->zval_snapshot_blob);
} }
/* }}} */ /* }}} */
@ -769,7 +769,7 @@ static PHP_METHOD(V8Js, clearPendingException)
c = Z_V8JS_CTX_OBJ_P(getThis()); c = Z_V8JS_CTX_OBJ_P(getThis());
if (Z_TYPE(c->pending_exception) == IS_OBJECT) { if (Z_TYPE(c->pending_exception) == IS_OBJECT) {
zval_dtor(&c->pending_exception); zval_ptr_dtor(&c->pending_exception);
ZVAL_NULL(&c->pending_exception); ZVAL_NULL(&c->pending_exception);
} }
} }

View File

@ -259,8 +259,8 @@ V8JS_METHOD(require)
} }
zend_end_try(); zend_end_try();
zval_dtor(&params[0]); zval_ptr_dtor(&params[0]);
zval_dtor(&params[1]); zval_ptr_dtor(&params[1]);
if(call_result == FAILURE) { if(call_result == FAILURE) {
return; return;
@ -275,7 +275,7 @@ V8JS_METHOD(require)
} }
if (Z_TYPE(normaliser_result) != IS_ARRAY) { if (Z_TYPE(normaliser_result) != IS_ARRAY) {
zval_dtor(&normaliser_result); zval_ptr_dtor(&normaliser_result);
info.GetReturnValue().Set(isolate->ThrowException(V8JS_SYM("Module normaliser didn't return an array"))); info.GetReturnValue().Set(isolate->ThrowException(V8JS_SYM("Module normaliser didn't return an array")));
return; return;
} }
@ -284,7 +284,7 @@ V8JS_METHOD(require)
int num_elements = zend_hash_num_elements(ht); int num_elements = zend_hash_num_elements(ht);
if(num_elements != 2) { if(num_elements != 2) {
zval_dtor(&normaliser_result); zval_ptr_dtor(&normaliser_result);
info.GetReturnValue().Set(isolate->ThrowException(V8JS_SYM("Module normaliser expected to return array of 2 strings"))); info.GetReturnValue().Set(isolate->ThrowException(V8JS_SYM("Module normaliser expected to return array of 2 strings")));
return; return;
} }
@ -309,7 +309,7 @@ V8JS_METHOD(require)
} }
ZEND_HASH_FOREACH_END(); ZEND_HASH_FOREACH_END();
zval_dtor(&normaliser_result); zval_ptr_dtor(&normaliser_result);
} }
char *normalised_module_id = (char *)emalloc(strlen(normalised_path)+1+strlen(module_name)+1); char *normalised_module_id = (char *)emalloc(strlen(normalised_path)+1+strlen(module_name)+1);
@ -377,7 +377,7 @@ V8JS_METHOD(require)
info.GetReturnValue().Set(isolate->ThrowException(V8JS_SYM("Module loader callback failed"))); info.GetReturnValue().Set(isolate->ThrowException(V8JS_SYM("Module loader callback failed")));
} }
zval_dtor(&params[0]); zval_ptr_dtor(&params[0]);
if (call_result == FAILURE) { if (call_result == FAILURE) {
efree(normalised_module_id); efree(normalised_module_id);

View File

@ -81,7 +81,7 @@ static void v8js_call_php_func(zend_object *object, zend_function *method_ptr, v
} }
efree(error); efree(error);
info.GetReturnValue().Set(return_value); info.GetReturnValue().Set(return_value);
zval_dtor(&fname); zval_ptr_dtor(&fname);
return; return;
} }
@ -138,7 +138,7 @@ failure:
/* Cleanup */ /* Cleanup */
if (argc) { if (argc) {
for (i = 0; i < fci.param_count; i++) { for (i = 0; i < fci.param_count; i++) {
zval_dtor(&fci.params[i]); zval_ptr_dtor(&fci.params[i]);
} }
efree(fci.params); efree(fci.params);
} }
@ -159,8 +159,8 @@ failure:
return_value = zval_to_v8js(&retval, isolate TSRMLS_CC); return_value = zval_to_v8js(&retval, isolate TSRMLS_CC);
} }
zval_dtor(&retval); zval_ptr_dtor(&retval);
zval_dtor(&fname); zval_ptr_dtor(&fname);
info.GetReturnValue().Set(return_value); info.GetReturnValue().Set(return_value);
} }
@ -264,7 +264,7 @@ static void v8js_weak_object_callback(const v8::WeakCallbackInfo<zend_object> &d
zend_object *object = data.GetParameter(); zend_object *object = data.GetParameter();
zval value; zval value;
ZVAL_OBJ(&value, object); ZVAL_OBJ(&value, object);
zval_dtor(&value); zval_ptr_dtor(&value);
v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0);
@ -643,7 +643,7 @@ v8::Local<v8::Value> v8js_named_property_callback(v8::Local<v8::String> property
/* Okay, let's call __get. */ /* Okay, let's call __get. */
zend_call_method_with_1_params(&zobject, ce, &ce->__get, ZEND_GET_FUNC_NAME, &php_value, &zname); zend_call_method_with_1_params(&zobject, ce, &ce->__get, ZEND_GET_FUNC_NAME, &php_value, &zname);
ret_value = zval_to_v8js(&php_value, isolate TSRMLS_CC); ret_value = zval_to_v8js(&php_value, isolate TSRMLS_CC);
zval_dtor(&php_value); zval_ptr_dtor(&php_value);
} }
} else if (callback_type == V8JS_PROP_SETTER) { } else if (callback_type == V8JS_PROP_SETTER) {
@ -701,7 +701,7 @@ v8::Local<v8::Value> v8js_named_property_callback(v8::Local<v8::String> property
ret_value = v8::Handle<v8::Value>(); ret_value = v8::Handle<v8::Value>();
} }
zval_dtor(&zname); zval_ptr_dtor(&zname);
} }
zend_string_release(method_name); zend_string_release(method_name);

View File

@ -282,7 +282,7 @@ int v8js_get_properties_hash(v8::Handle<v8::Value> jsValue, HashTable *retval, i
} }
else { else {
if (v8js_to_zval(jsVal, &value, flags, isolate TSRMLS_CC) == FAILURE) { if (v8js_to_zval(jsVal, &value, flags, isolate TSRMLS_CC) == FAILURE) {
zval_dtor(&value); zval_ptr_dtor(&value);
return FAILURE; return FAILURE;
} }
} }

View File

@ -479,7 +479,7 @@ PHP_METHOD(V8Function, __wakeup)
static void v8js_v8generator_free_storage(zend_object *object) /* {{{ */ static void v8js_v8generator_free_storage(zend_object *object) /* {{{ */
{ {
v8js_v8generator *c = v8js_v8generator_fetch_object(object); v8js_v8generator *c = v8js_v8generator_fetch_object(object);
zval_dtor(&c->value); zval_ptr_dtor(&c->value);
v8js_v8object_free_storage(object); v8js_v8object_free_storage(object);
} }
@ -533,7 +533,7 @@ static void v8js_v8generator_next(v8js_v8generator *g) /* {{{ */
v8::Local<v8::Value> val = resultObj->Get(V8JS_STR("value")); v8::Local<v8::Value> val = resultObj->Get(V8JS_STR("value"));
v8::Local<v8::Value> done = resultObj->Get(V8JS_STR("done")); v8::Local<v8::Value> done = resultObj->Get(V8JS_STR("done"));
zval_dtor(&g->value); zval_ptr_dtor(&g->value);
v8js_to_zval(val, &g->value, 0, isolate); v8js_to_zval(val, &g->value, 0, isolate);
g->done = done->IsTrue(); g->done = done->IsTrue();