0
0
mirror of https://github.com/phpv8/v8js.git synced 2024-11-08 12:38:41 +00:00

v8js_object_export: add size checks + precission down casts

This commit is contained in:
Stefan Siegl 2017-03-10 23:49:18 +01:00
parent 7625d9b94f
commit db7c81d4fa

View File

@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2016 The PHP Group |
| Copyright (c) 1997-2017 The PHP Group |
+----------------------------------------------------------------------+
| http://www.opensource.org/licenses/mit-license.php MIT License |
+----------------------------------------------------------------------+
@ -18,6 +18,7 @@
#include "php_v8js_macros.h"
#include "v8js_array_access.h"
#include "v8js_exceptions.h"
#include "v8js_generator_export.h"
#include "v8js_object_export.h"
#include "v8js_v8object_class.h"
@ -42,7 +43,7 @@ static void v8js_call_php_func(zend_object *object, zend_function *method_ptr, v
zval fname, retval;
unsigned int argc = info.Length(), min_num_args = 0, max_num_args = 0;
char *error;
int error_len;
zend_ulong error_len;
unsigned int i;
v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0);
@ -77,7 +78,14 @@ static void v8js_call_php_func(zend_object *object, zend_function *method_ptr, v
(argc < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
argc);
return_value = V8JS_THROW(isolate, TypeError, error, error_len);
if (error_len > std::numeric_limits<int>::max()) {
zend_throw_exception(php_ce_v8js_exception,
"Generated error message length exceeds maximum supported length", 0);
}
else {
return_value = V8JS_THROW(isolate, TypeError, error, static_cast<int>(error_len));
}
if (object->ce == zend_ce_closure) {
zend_string_release(method_ptr->internal_function.function_name);
efree(method_ptr);
@ -100,7 +108,15 @@ static void v8js_call_php_func(zend_object *object, zend_function *method_ptr, v
} else {
if (v8js_to_zval(info[i], &fci.params[i], ctx->flags, isolate TSRMLS_CC) == FAILURE) {
error_len = spprintf(&error, 0, "converting parameter #%d passed to %s() failed", i + 1, method_ptr->common.function_name);
return_value = V8JS_THROW(isolate, Error, error, error_len);
if (error_len > std::numeric_limits<int>::max()) {
zend_throw_exception(php_ce_v8js_exception,
"Generated error message length exceeds maximum supported length", 0);
}
else {
return_value = V8JS_THROW(isolate, Error, error, static_cast<int>(error_len));
}
efree(error);
goto failure;
}
@ -311,7 +327,7 @@ static void v8js_named_property_enumerator(const v8::PropertyCallbackInfo<v8::Ar
void *ptr;
HashTable *proptable;
zend_string *key;
ulong index;
zend_ulong index;
zend_object *object = reinterpret_cast<zend_object *>(self->GetAlignedPointerFromInternalField(1));
ce = object->ce;
@ -340,11 +356,23 @@ static void v8js_named_property_enumerator(const v8::PropertyCallbackInfo<v8::Ar
IS_MAGIC_FUNC(ZEND_ISSET_FUNC_NAME)) {
continue;
}
v8::Local<v8::String> method_name = V8JS_ZSTR(method_ptr->common.function_name);
v8::Local<v8::String> method_name;
// rename PHP special method names to JS equivalents.
if (IS_MAGIC_FUNC(ZEND_TOSTRING_FUNC_NAME)) {
method_name = V8JS_SYM("toString");
}
else {
if (ZSTR_LEN(method_ptr->common.function_name) > std::numeric_limits<int>::max()) {
zend_throw_exception(php_ce_v8js_exception,
"Method name length exceeds maximum supported length", 0);
return;
}
method_name = V8JS_STRL(ZSTR_VAL(method_ptr->common.function_name), static_cast<int>(ZSTR_LEN(method_ptr->common.function_name)));
}
result->Set(result_len++, method_name);
} ZEND_HASH_FOREACH_END();
@ -362,13 +390,20 @@ static void v8js_named_property_enumerator(const v8::PropertyCallbackInfo<v8::Ar
if(ZSTR_VAL(key)[0] == '\0') {
continue;
}
if (ZSTR_LEN(key) + 1 > std::numeric_limits<int>::max()) {
zend_throw_exception(php_ce_v8js_exception,
"Object key length exceeds maximum supported length", 0);
continue;
}
// prefix enumerated property names with '$' so they can be
// dereferenced unambiguously (ie, don't conflict with method
// names)
char *prefixed = static_cast<char *>(emalloc(ZSTR_LEN(key) + 2));
prefixed[0] = '$';
strncpy(prefixed + 1, ZSTR_VAL(key), ZSTR_LEN(key) + 1);
result->Set(result_len++, V8JS_STRL(prefixed, ZSTR_LEN(key) + 1));
result->Set(result_len++, V8JS_STRL(prefixed, static_cast<int>(ZSTR_LEN(key) + 1)));
efree(prefixed);
} else {
// even numeric indices are enumerated as strings in JavaScript
@ -425,10 +460,10 @@ static void v8js_fake_call_impl(const v8::FunctionCallbackInfo<v8::Value>& info)
{
v8::Isolate *isolate = info.GetIsolate();
v8::Local<v8::Object> self = info.Holder();
v8::Handle<v8::Value> return_value;
v8::Handle<v8::Value> return_value = V8JS_NULL;
char *error;
int error_len;
size_t error_len;
V8JS_TSRMLS_FETCH();
zend_class_entry *ce;
@ -440,16 +475,33 @@ static void v8js_fake_call_impl(const v8::FunctionCallbackInfo<v8::Value>& info)
error_len = spprintf(&error, 0,
"%s::__call expects 2 parameters, %d given",
ce->name, (int) info.Length());
return_value = V8JS_THROW(isolate, TypeError, error, error_len);
if (error_len > std::numeric_limits<int>::max()) {
zend_throw_exception(php_ce_v8js_exception,
"Generated error message length exceeds maximum supported length", 0);
}
else {
return_value = V8JS_THROW(isolate, TypeError, error, static_cast<int>(error_len));
}
efree(error);
info.GetReturnValue().Set(return_value);
return;
}
if (!info[1]->IsArray()) {
error_len = spprintf(&error, 0,
"%s::__call expects 2nd parameter to be an array",
ce->name);
return_value = V8JS_THROW(isolate, TypeError, error, error_len);
if (error_len > std::numeric_limits<int>::max()) {
zend_throw_exception(php_ce_v8js_exception,
"Generated error message length exceeds maximum supported length", 0);
}
else {
return_value = V8JS_THROW(isolate, TypeError, error, static_cast<int>(error_len));
}
efree(error);
info.GetReturnValue().Set(return_value);
return;
@ -462,7 +514,15 @@ static void v8js_fake_call_impl(const v8::FunctionCallbackInfo<v8::Value>& info)
error_len = spprintf(&error, 0,
"%s::__call expects fewer than a million arguments",
ce->name);
return_value = V8JS_THROW(isolate, TypeError, error, error_len);
if (error_len > std::numeric_limits<int>::max()) {
zend_throw_exception(php_ce_v8js_exception,
"Generated error message length exceeds maximum supported length", 0);
}
else {
return_value = V8JS_THROW(isolate, TypeError, error, static_cast<int>(error_len));
}
efree(error);
info.GetReturnValue().Set(return_value);
return;
@ -484,7 +544,15 @@ static void v8js_fake_call_impl(const v8::FunctionCallbackInfo<v8::Value>& info)
error_len = spprintf(&error, 0,
"%s::__call to %s method %s", ce->name,
(method_ptr == NULL) ? "undefined" : "non-public", method_name);
return_value = V8JS_THROW(isolate, TypeError, error, error_len);
if (error_len > std::numeric_limits<int>::max()) {
zend_throw_exception(php_ce_v8js_exception,
"Generated error message length exceeds maximum supported length", 0);
}
else {
return_value = V8JS_THROW(isolate, TypeError, error, static_cast<int>(error_len));
}
efree(error);
info.GetReturnValue().Set(return_value);
return;
@ -759,7 +827,13 @@ static v8::Handle<v8::Object> v8js_wrap_object(v8::Isolate *isolate, zend_class_
/* No cached v8::FunctionTemplate available as of yet, create one. */
new_tpl = v8::FunctionTemplate::New(isolate, 0);
new_tpl->SetClassName(V8JS_ZSTR(ce->name));
if (ZSTR_LEN(ce->name) > std::numeric_limits<int>::max()) {
zend_throw_exception(php_ce_v8js_exception,
"Class name length exceeds maximum supported length", 0);
return v8::Local<v8::Object>();
}
new_tpl->SetClassName(V8JS_STRL(ZSTR_VAL(ce->name), static_cast<int>(ZSTR_LEN(ce->name))));
new_tpl->InstanceTemplate()->SetInternalFieldCount(2);
if (ce == zend_ce_closure) {
@ -855,7 +929,7 @@ static v8::Handle<v8::Object> v8js_wrap_array_to_object(v8::Isolate *isolate, zv
{
int i;
zend_string *key;
ulong index;
zend_ulong index;
v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0);
v8::Local<v8::FunctionTemplate> new_tpl;
@ -899,9 +973,23 @@ static v8::Handle<v8::Object> v8js_wrap_array_to_object(v8::Isolate *isolate, zv
}
continue;
}
newobj->Set(V8JS_ZSTR(key), zval_to_v8js(data, isolate TSRMLS_CC));
if (ZSTR_LEN(key) > std::numeric_limits<int>::max()) {
zend_throw_exception(php_ce_v8js_exception,
"Object key length exceeds maximum supported length", 0);
continue;
}
newobj->Set(V8JS_STRL(ZSTR_VAL(key), static_cast<int>(ZSTR_LEN(key))),
zval_to_v8js(data, isolate));
} else {
newobj->Set(index, zval_to_v8js(data, isolate TSRMLS_CC));
if (index > std::numeric_limits<uint32_t>::max()) {
zend_throw_exception(php_ce_v8js_exception,
"Array index exceeds maximum supported bound", 0);
continue;
}
newobj->Set(static_cast<uint32_t>(index), zval_to_v8js(data, isolate));
}
if (tmp_ht) {