[d8] Add ValueSerializer JS api for better fuzzing
Change-Id: Ib94979f4cf7f52a1544f2b3c0d51c0266a4fa14c Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3586985 Reviewed-by: Marja Hölttä <marja@chromium.org> Commit-Queue: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/main@{#80223}
This commit is contained in:
parent
5647e65451
commit
b4165a3590
55
src/d8/d8.cc
55
src/d8/d8.cc
@ -2281,6 +2281,50 @@ void Shell::SetPromiseHooks(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
#endif // V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
|
||||
}
|
||||
|
||||
void Shell::SerializerSerialize(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
HandleScope handle_scope(isolate);
|
||||
Local<Context> context = isolate->GetCurrentContext();
|
||||
|
||||
ValueSerializer serializer(isolate);
|
||||
serializer.WriteHeader();
|
||||
for (int i = 0; i < args.Length(); i++) {
|
||||
bool ok;
|
||||
if (!serializer.WriteValue(context, args[i]).To(&ok)) return;
|
||||
}
|
||||
Local<v8::ArrayBuffer> buffer;
|
||||
{
|
||||
std::pair<uint8_t*, size_t> pair = serializer.Release();
|
||||
buffer = ArrayBuffer::New(isolate, pair.second);
|
||||
memcpy(buffer->GetBackingStore()->Data(), pair.first, pair.second);
|
||||
free(pair.first);
|
||||
}
|
||||
args.GetReturnValue().Set(buffer);
|
||||
}
|
||||
|
||||
void Shell::SerializerDeserialize(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
HandleScope handle_scope(isolate);
|
||||
Local<Context> context = isolate->GetCurrentContext();
|
||||
|
||||
if (!args[0]->IsArrayBuffer()) {
|
||||
isolate->ThrowError("Can only deserialize from an ArrayBuffer");
|
||||
return;
|
||||
}
|
||||
std::shared_ptr<BackingStore> backing_store =
|
||||
args[0].As<ArrayBuffer>()->GetBackingStore();
|
||||
ValueDeserializer deserializer(
|
||||
isolate, static_cast<const uint8_t*>(backing_store->Data()),
|
||||
backing_store->ByteLength());
|
||||
bool ok;
|
||||
if (!deserializer.ReadHeader(context).To(&ok)) return;
|
||||
Local<Value> result;
|
||||
if (!deserializer.ReadValue(context).ToLocal(&result)) return;
|
||||
args.GetReturnValue().Set(result);
|
||||
}
|
||||
|
||||
void WriteToFile(FILE* file, const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
for (int i = 0; i < args.Length(); i++) {
|
||||
HandleScope handle_scope(args.GetIsolate());
|
||||
@ -3195,6 +3239,17 @@ Local<ObjectTemplate> Shell::CreateD8Template(Isolate* isolate) {
|
||||
Local<Signature>(), 4));
|
||||
d8_template->Set(isolate, "promise", promise_template);
|
||||
}
|
||||
{
|
||||
Local<ObjectTemplate> serializer_template = ObjectTemplate::New(isolate);
|
||||
serializer_template->Set(
|
||||
isolate, "serialize",
|
||||
FunctionTemplate::New(isolate, SerializerSerialize));
|
||||
serializer_template->Set(
|
||||
isolate, "deserialize",
|
||||
FunctionTemplate::New(isolate, SerializerDeserialize, Local<Value>(),
|
||||
Local<Signature>(), 1));
|
||||
d8_template->Set(isolate, "serializer", serializer_template);
|
||||
}
|
||||
return d8_template;
|
||||
}
|
||||
|
||||
|
@ -569,6 +569,11 @@ class Shell : public i::AllStatic {
|
||||
|
||||
static void SetPromiseHooks(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
static void SerializerSerialize(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SerializerDeserialize(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
static void Print(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void PrintErr(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void WriteStdout(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
48
test/mjsunit/value-serializer.js
Normal file
48
test/mjsunit/value-serializer.js
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Test the basic d8 value serializer interface
|
||||
|
||||
var largeArray = [];
|
||||
largeArray[0xFFFF00] = 123;
|
||||
|
||||
let proto_obj = { fn1() { return 1 } }
|
||||
let obj_with_enum_cache = {
|
||||
__proto__: proto_obj,
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: "c"
|
||||
};
|
||||
|
||||
for (let k in obj_with_enum_cache) {
|
||||
// do something
|
||||
obj_with_enum_cache.a += obj_with_enum_cache.fn1();
|
||||
}
|
||||
let string_1 = "aasdfasdfasdfasdf asd fa sdf asdf as dfa sdf asd f"
|
||||
let string_2 = "aasdfasdfasdfasdf asd fa sdf UC16\u2028asdf as dfa sdf asd f"
|
||||
var objects = [
|
||||
true, false, null, undefined,
|
||||
1, -1, 1.1, -2.2, -0, 0,
|
||||
9007199254740991.0, 9007199254740991.0 + 10,
|
||||
-9007199254740992.0, -9007199254740992.0 - 10,
|
||||
Infinity, -Infinity, NaN,
|
||||
string_1, string_1+"b", string_1.slice(1),
|
||||
string_2, string_2+"b", string_2.slice(1),
|
||||
{}, {1:1}, {a:1}, {1:1, 2:2}, Object.create(null),
|
||||
obj_with_enum_cache,
|
||||
[], [{}, {}], [1, 1, 1], [1.1, 1.1, 1.1, 1.1, 2], largeArray,
|
||||
// new Proxy({},{}),
|
||||
new Date(), new String(" a"),
|
||||
new Uint8Array(12), new Float32Array([1, 2, 4, 5]),
|
||||
new Uint8ClampedArray(2048),
|
||||
/asdf/, new RegExp(),
|
||||
new Map(), new Set(),
|
||||
|
||||
];
|
||||
|
||||
for (var o of objects) {
|
||||
const serialised = d8.serializer.serialize(o)
|
||||
const deserialised = d8.serializer.deserialize(serialised);
|
||||
assertEquals(typeof deserialised, typeof o);
|
||||
}
|
Loading…
Reference in New Issue
Block a user