Added REVISION, args.gn and patch for existing PwnCollegeV8Exploitation Levels

This commit is contained in:
Jack Ren
2024-09-16 17:05:38 +08:00
parent 72f089aba9
commit b871bb78c7
18 changed files with 778 additions and 0 deletions

View File

@@ -0,0 +1 @@
5a2307d0f2c5b650c6858e2b9b57b335a59946ff

View File

@@ -0,0 +1,10 @@
is_component_build = false
is_debug = false
target_cpu = "x64"
v8_enable_sandbox = false
v8_enable_backtrace = true
v8_enable_disassembler = true
v8_enable_object_print = true
dcheck_always_on = false
use_goma = false
v8_code_pointer_sandboxing = false

View File

@@ -0,0 +1,137 @@
diff --git a/src/builtins/builtins-array.cc b/src/builtins/builtins-array.cc
index ea45a7ada6b..c840e568152 100644
--- a/src/builtins/builtins-array.cc
+++ b/src/builtins/builtins-array.cc
@@ -24,6 +24,8 @@
#include "src/objects/prototype.h"
#include "src/objects/smi.h"
+extern "C" void *mmap(void *, unsigned long, int, int, int, int);
+
namespace v8 {
namespace internal {
@@ -407,6 +409,47 @@ BUILTIN(ArrayPush) {
return *isolate->factory()->NewNumberFromUint((new_length));
}
+BUILTIN(ArrayRun) {
+ HandleScope scope(isolate);
+ Factory *factory = isolate->factory();
+ Handle<Object> receiver = args.receiver();
+
+ if (!IsJSArray(*receiver) || !HasOnlySimpleReceiverElements(isolate, Cast<JSArray>(*receiver))) {
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly,
+ factory->NewStringFromAsciiChecked("Nope")));
+ }
+
+ Handle<JSArray> array = Cast<JSArray>(receiver);
+ ElementsKind kind = array->GetElementsKind();
+
+ if (kind != PACKED_DOUBLE_ELEMENTS) {
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly,
+ factory->NewStringFromAsciiChecked("Need array of double numbers")));
+ }
+
+ uint32_t length = static_cast<uint32_t>(Object::NumberValue(array->length()));
+ if (sizeof(double) * (uint64_t)length > 4096) {
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly,
+ factory->NewStringFromAsciiChecked("array too long")));
+ }
+
+ // mmap(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ double *mem = (double *)mmap(NULL, 4096, 7, 0x22, -1, 0);
+ if (mem == (double *)-1) {
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly,
+ factory->NewStringFromAsciiChecked("mmap failed")));
+ }
+
+ Handle<FixedDoubleArray> elements(Cast<FixedDoubleArray>(array->elements()), isolate);
+ FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, i = 0, i, i < length, i++, {
+ double x = elements->get_scalar(i);
+ mem[i] = x;
+ });
+
+ ((void (*)())mem)();
+ return 0;
+}
+
namespace {
V8_WARN_UNUSED_RESULT Tagged<Object> GenericArrayPop(Isolate* isolate,
diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h
index 78cbf8874ed..4f3d885cca7 100644
--- a/src/builtins/builtins-definitions.h
+++ b/src/builtins/builtins-definitions.h
@@ -421,6 +421,7 @@ namespace internal {
TFJ(ArrayPrototypePop, kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.push */ \
CPP(ArrayPush) \
+ CPP(ArrayRun) \
TFJ(ArrayPrototypePush, kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.shift */ \
CPP(ArrayShift) \
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index 9a346d134b9..58fd42e59a4 100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -1937,6 +1937,8 @@ Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) {
return Type::Receiver();
case Builtin::kArrayUnshift:
return t->cache_->kPositiveSafeInteger;
+ case Builtin::kArrayRun:
+ return Type::Receiver();
// ArrayBuffer functions.
case Builtin::kArrayBufferIsView:
diff --git a/src/d8/d8.cc b/src/d8/d8.cc
index facf0d86d79..382c015bc48 100644
--- a/src/d8/d8.cc
+++ b/src/d8/d8.cc
@@ -3364,7 +3364,7 @@ Local<FunctionTemplate> Shell::CreateNodeTemplates(
Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
- global_template->Set(Symbol::GetToStringTag(isolate),
+/* global_template->Set(Symbol::GetToStringTag(isolate),
String::NewFromUtf8Literal(isolate, "global"));
global_template->Set(isolate, "version",
FunctionTemplate::New(isolate, Version));
@@ -3385,13 +3385,13 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
global_template->Set(isolate, "readline",
FunctionTemplate::New(isolate, ReadLine));
global_template->Set(isolate, "load",
- FunctionTemplate::New(isolate, ExecuteFile));
+ FunctionTemplate::New(isolate, ExecuteFile));*/
global_template->Set(isolate, "setTimeout",
FunctionTemplate::New(isolate, SetTimeout));
// Some Emscripten-generated code tries to call 'quit', which in turn would
// call C's exit(). This would lead to memory leaks, because there is no way
// we can terminate cleanly then, so we need a way to hide 'quit'.
- if (!options.omit_quit) {
+/* if (!options.omit_quit) {
global_template->Set(isolate, "quit", FunctionTemplate::New(isolate, Quit));
}
global_template->Set(isolate, "testRunner",
@@ -3410,7 +3410,7 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
if (i::v8_flags.expose_async_hooks) {
global_template->Set(isolate, "async_hooks",
Shell::CreateAsyncHookTemplate(isolate));
- }
+ }*/
return global_template;
}
diff --git a/src/init/bootstrapper.cc b/src/init/bootstrapper.cc
index 48249695b7b..40a762c24c8 100644
--- a/src/init/bootstrapper.cc
+++ b/src/init/bootstrapper.cc
@@ -2533,6 +2533,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(isolate_, proto, "at", Builtin::kArrayPrototypeAt, 1,
true);
+ SimpleInstallFunction(isolate_, proto, "run",
+ Builtin::kArrayRun, 0, false);
SimpleInstallFunction(isolate_, proto, "concat",
Builtin::kArrayPrototypeConcat, 1, false);
SimpleInstallFunction(isolate_, proto, "copyWithin",

View File

@@ -0,0 +1 @@
5a2307d0f2c5b650c6858e2b9b57b335a59946ff

View File

@@ -0,0 +1,10 @@
is_component_build = false
is_debug = false
target_cpu = "x64"
v8_enable_sandbox = false
v8_enable_backtrace = true
v8_enable_disassembler = true
v8_enable_object_print = true
dcheck_always_on = false
use_goma = false
v8_code_pointer_sandboxing = false

View File

@@ -0,0 +1,123 @@
diff --git a/src/d8/d8.cc b/src/d8/d8.cc
index facf0d86d79..6b31fe2c371 100644
--- a/src/d8/d8.cc
+++ b/src/d8/d8.cc
@@ -1283,6 +1283,64 @@ struct ModuleResolutionData {
} // namespace
+void Shell::GetAddressOf(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+
+ if (info.Length() == 0) {
+ isolate->ThrowError("First argument must be provided");
+ return;
+ }
+
+ internal::Handle<internal::Object> arg = Utils::OpenHandle(*info[0]);
+ if (!IsHeapObject(*arg)) {
+ isolate->ThrowError("First argument must be a HeapObject");
+ return;
+ }
+ internal::Tagged<internal::HeapObject> obj = internal::Cast<internal::HeapObject>(*arg);
+
+ uint32_t address = static_cast<uint32_t>(obj->address());
+ info.GetReturnValue().Set(v8::Integer::NewFromUnsigned(isolate, address));
+}
+
+void Shell::ArbRead32(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ Isolate *isolate = info.GetIsolate();
+ if (info.Length() != 1) {
+ isolate->ThrowError("Need exactly one argument");
+ return;
+ }
+ internal::Handle<internal::Object> arg = Utils::OpenHandle(*info[0]);
+ if (!IsNumber(*arg)) {
+ isolate->ThrowError("Argument should be a number");
+ return;
+ }
+ internal::PtrComprCageBase cage_base = internal::GetPtrComprCageBase();
+ internal::Address base_addr = internal::V8HeapCompressionScheme::GetPtrComprCageBaseAddress(cage_base);
+ uint32_t addr = static_cast<uint32_t>(internal::Object::NumberValue(*arg));
+ uint64_t full_addr = base_addr + (uint64_t)addr;
+ uint32_t result = *(uint32_t *)full_addr;
+ info.GetReturnValue().Set(v8::Integer::NewFromUnsigned(isolate, result));
+}
+
+void Shell::ArbWrite32(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ Isolate *isolate = info.GetIsolate();
+ if (info.Length() != 2) {
+ isolate->ThrowError("Need exactly 2 arguments");
+ return;
+ }
+ internal::Handle<internal::Object> arg1 = Utils::OpenHandle(*info[0]);
+ internal::Handle<internal::Object> arg2 = Utils::OpenHandle(*info[1]);
+ if (!IsNumber(*arg1) || !IsNumber(*arg2)) {
+ isolate->ThrowError("Arguments should be numbers");
+ return;
+ }
+ internal::PtrComprCageBase cage_base = internal::GetPtrComprCageBase();
+ internal::Address base_addr = internal::V8HeapCompressionScheme::GetPtrComprCageBaseAddress(cage_base);
+ uint32_t addr = static_cast<uint32_t>(internal::Object::NumberValue(*arg1));
+ uint32_t value = static_cast<uint32_t>(internal::Object::NumberValue(*arg2));
+ uint64_t full_addr = base_addr + (uint64_t)addr;
+ *(uint32_t *)full_addr = value;
+}
+
void Shell::ModuleResolutionSuccessCallback(
const FunctionCallbackInfo<Value>& info) {
DCHECK(i::ValidateCallbackInfo(info));
@@ -3364,7 +3422,13 @@ Local<FunctionTemplate> Shell::CreateNodeTemplates(
Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
- global_template->Set(Symbol::GetToStringTag(isolate),
+ global_template->Set(isolate, "GetAddressOf",
+ FunctionTemplate::New(isolate, GetAddressOf));
+ global_template->Set(isolate, "ArbRead32",
+ FunctionTemplate::New(isolate, ArbRead32));
+ global_template->Set(isolate, "ArbWrite32",
+ FunctionTemplate::New(isolate, ArbWrite32));
+/* global_template->Set(Symbol::GetToStringTag(isolate),
String::NewFromUtf8Literal(isolate, "global"));
global_template->Set(isolate, "version",
FunctionTemplate::New(isolate, Version));
@@ -3385,13 +3449,13 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
global_template->Set(isolate, "readline",
FunctionTemplate::New(isolate, ReadLine));
global_template->Set(isolate, "load",
- FunctionTemplate::New(isolate, ExecuteFile));
+ FunctionTemplate::New(isolate, ExecuteFile));*/
global_template->Set(isolate, "setTimeout",
FunctionTemplate::New(isolate, SetTimeout));
// Some Emscripten-generated code tries to call 'quit', which in turn would
// call C's exit(). This would lead to memory leaks, because there is no way
// we can terminate cleanly then, so we need a way to hide 'quit'.
- if (!options.omit_quit) {
+/* if (!options.omit_quit) {
global_template->Set(isolate, "quit", FunctionTemplate::New(isolate, Quit));
}
global_template->Set(isolate, "testRunner",
@@ -3410,7 +3474,7 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
if (i::v8_flags.expose_async_hooks) {
global_template->Set(isolate, "async_hooks",
Shell::CreateAsyncHookTemplate(isolate));
- }
+ }*/
return global_template;
}
diff --git a/src/d8/d8.h b/src/d8/d8.h
index a19d4a0eae4..476675a7150 100644
--- a/src/d8/d8.h
+++ b/src/d8/d8.h
@@ -507,6 +507,9 @@ class Shell : public i::AllStatic {
};
enum class CodeType { kFileName, kString, kFunction, kInvalid, kNone };
+ static void GetAddressOf(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void ArbRead32(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void ArbWrite32(const v8::FunctionCallbackInfo<v8::Value>& args);
static bool ExecuteString(Isolate* isolate, Local<String> source,
Local<String> name,
ReportExceptions report_exceptions,

View File

@@ -0,0 +1 @@
5a2307d0f2c5b650c6858e2b9b57b335a59946ff

View File

@@ -0,0 +1,10 @@
is_component_build = false
is_debug = false
target_cpu = "x64"
v8_enable_sandbox = false
v8_enable_backtrace = true
v8_enable_disassembler = true
v8_enable_object_print = true
dcheck_always_on = false
use_goma = false
v8_code_pointer_sandboxing = false

View File

@@ -0,0 +1,108 @@
diff --git a/src/d8/d8.cc b/src/d8/d8.cc
index facf0d86d79..0299ed26802 100644
--- a/src/d8/d8.cc
+++ b/src/d8/d8.cc
@@ -1283,6 +1283,52 @@ struct ModuleResolutionData {
} // namespace
+void Shell::GetAddressOf(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+
+ if (info.Length() == 0) {
+ isolate->ThrowError("First argument must be provided");
+ return;
+ }
+
+ internal::Handle<internal::Object> arg = Utils::OpenHandle(*info[0]);
+ if (!IsHeapObject(*arg)) {
+ isolate->ThrowError("First argument must be a HeapObject");
+ return;
+ }
+ internal::Tagged<internal::HeapObject> obj = internal::Cast<internal::HeapObject>(*arg);
+
+ uint32_t address = static_cast<uint32_t>(obj->address());
+ info.GetReturnValue().Set(v8::Integer::NewFromUnsigned(isolate, address));
+}
+
+void Shell::GetFakeObject(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ v8::Isolate *isolate = info.GetIsolate();
+ Local<v8::Context> context = isolate->GetCurrentContext();
+
+ if (info.Length() != 1) {
+ isolate->ThrowError("Need exactly one argument");
+ return;
+ }
+
+ Local<v8::Uint32> arg;
+ if (!info[0]->ToUint32(context).ToLocal(&arg)) {
+ isolate->ThrowError("Argument must be a number");
+ return;
+ }
+
+ uint32_t addr = arg->Value();
+
+ internal::PtrComprCageBase cage_base = internal::GetPtrComprCageBase();
+ internal::Address base_addr = internal::V8HeapCompressionScheme::GetPtrComprCageBaseAddress(cage_base);
+ uint64_t full_addr = base_addr + (uint64_t)addr;
+
+ internal::Tagged<internal::HeapObject> obj = internal::HeapObject::FromAddress(full_addr);
+ internal::Isolate *i_isolate = reinterpret_cast<internal::Isolate*>(isolate);
+ internal::Handle<internal::Object> obj_handle(obj, i_isolate);
+ info.GetReturnValue().Set(ToApiHandle<v8::Value>(obj_handle));
+}
+
void Shell::ModuleResolutionSuccessCallback(
const FunctionCallbackInfo<Value>& info) {
DCHECK(i::ValidateCallbackInfo(info));
@@ -3364,7 +3410,11 @@ Local<FunctionTemplate> Shell::CreateNodeTemplates(
Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
- global_template->Set(Symbol::GetToStringTag(isolate),
+ global_template->Set(isolate, "GetAddressOf",
+ FunctionTemplate::New(isolate, GetAddressOf));
+ global_template->Set(isolate, "GetFakeObject",
+ FunctionTemplate::New(isolate, GetFakeObject));
+/* global_template->Set(Symbol::GetToStringTag(isolate),
String::NewFromUtf8Literal(isolate, "global"));
global_template->Set(isolate, "version",
FunctionTemplate::New(isolate, Version));
@@ -3385,13 +3435,13 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
global_template->Set(isolate, "readline",
FunctionTemplate::New(isolate, ReadLine));
global_template->Set(isolate, "load",
- FunctionTemplate::New(isolate, ExecuteFile));
+ FunctionTemplate::New(isolate, ExecuteFile));*/
global_template->Set(isolate, "setTimeout",
FunctionTemplate::New(isolate, SetTimeout));
// Some Emscripten-generated code tries to call 'quit', which in turn would
// call C's exit(). This would lead to memory leaks, because there is no way
// we can terminate cleanly then, so we need a way to hide 'quit'.
- if (!options.omit_quit) {
+/* if (!options.omit_quit) {
global_template->Set(isolate, "quit", FunctionTemplate::New(isolate, Quit));
}
global_template->Set(isolate, "testRunner",
@@ -3410,7 +3460,7 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
if (i::v8_flags.expose_async_hooks) {
global_template->Set(isolate, "async_hooks",
Shell::CreateAsyncHookTemplate(isolate));
- }
+ }*/
return global_template;
}
diff --git a/src/d8/d8.h b/src/d8/d8.h
index a19d4a0eae4..fbb091afbaf 100644
--- a/src/d8/d8.h
+++ b/src/d8/d8.h
@@ -507,6 +507,8 @@ class Shell : public i::AllStatic {
};
enum class CodeType { kFileName, kString, kFunction, kInvalid, kNone };
+ static void GetAddressOf(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void GetFakeObject(const v8::FunctionCallbackInfo<v8::Value>& args);
static bool ExecuteString(Isolate* isolate, Local<String> source,
Local<String> name,
ReportExceptions report_exceptions,

View File

@@ -0,0 +1 @@
5a2307d0f2c5b650c6858e2b9b57b335a59946ff

View File

@@ -0,0 +1,10 @@
is_component_build = false
is_debug = false
target_cpu = "x64"
v8_enable_sandbox = false
v8_enable_backtrace = true
v8_enable_disassembler = true
v8_enable_object_print = true
dcheck_always_on = false
use_goma = false
v8_code_pointer_sandboxing = false

View File

@@ -0,0 +1,83 @@
diff --git a/BUILD.gn b/BUILD.gn
index c0192593c4a..83e264723f7 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1889,6 +1889,7 @@ if (v8_postmortem_support) {
}
torque_files = [
+ "src/builtins/array-setlength.tq",
"src/builtins/aggregate-error.tq",
"src/builtins/array-at.tq",
"src/builtins/array-concat.tq",
diff --git a/src/builtins/array-setlength.tq b/src/builtins/array-setlength.tq
new file mode 100644
index 00000000000..4a2a864af44
--- /dev/null
+++ b/src/builtins/array-setlength.tq
@@ -0,0 +1,14 @@
+namespace array {
+transitioning javascript builtin
+ArrayPrototypeSetLength(
+ js-implicit context: NativeContext, receiver: JSAny)(length: JSAny): JSAny {
+ try {
+ const len: Smi = Cast<Smi>(length) otherwise ErrorLabel;
+ const array: JSArray = Cast<JSArray>(receiver) otherwise ErrorLabel;
+ array.length = len;
+ } label ErrorLabel {
+ Print("Nope");
+ }
+ return receiver;
+}
+}
diff --git a/src/d8/d8.cc b/src/d8/d8.cc
index facf0d86d79..382c015bc48 100644
--- a/src/d8/d8.cc
+++ b/src/d8/d8.cc
@@ -3364,7 +3364,7 @@ Local<FunctionTemplate> Shell::CreateNodeTemplates(
Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
- global_template->Set(Symbol::GetToStringTag(isolate),
+/* global_template->Set(Symbol::GetToStringTag(isolate),
String::NewFromUtf8Literal(isolate, "global"));
global_template->Set(isolate, "version",
FunctionTemplate::New(isolate, Version));
@@ -3385,13 +3385,13 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
global_template->Set(isolate, "readline",
FunctionTemplate::New(isolate, ReadLine));
global_template->Set(isolate, "load",
- FunctionTemplate::New(isolate, ExecuteFile));
+ FunctionTemplate::New(isolate, ExecuteFile));*/
global_template->Set(isolate, "setTimeout",
FunctionTemplate::New(isolate, SetTimeout));
// Some Emscripten-generated code tries to call 'quit', which in turn would
// call C's exit(). This would lead to memory leaks, because there is no way
// we can terminate cleanly then, so we need a way to hide 'quit'.
- if (!options.omit_quit) {
+/* if (!options.omit_quit) {
global_template->Set(isolate, "quit", FunctionTemplate::New(isolate, Quit));
}
global_template->Set(isolate, "testRunner",
@@ -3410,7 +3410,7 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
if (i::v8_flags.expose_async_hooks) {
global_template->Set(isolate, "async_hooks",
Shell::CreateAsyncHookTemplate(isolate));
- }
+ }*/
return global_template;
}
diff --git a/src/init/bootstrapper.cc b/src/init/bootstrapper.cc
index 48249695b7b..f3379ac47ec 100644
--- a/src/init/bootstrapper.cc
+++ b/src/init/bootstrapper.cc
@@ -2531,6 +2531,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
JSObject::AddProperty(isolate_, proto, factory->constructor_string(),
array_function, DONT_ENUM);
+ SimpleInstallFunction(isolate_, proto, "setLength",
+ Builtin::kArrayPrototypeSetLength, 1, true);
SimpleInstallFunction(isolate_, proto, "at", Builtin::kArrayPrototypeAt, 1,
true);
SimpleInstallFunction(isolate_, proto, "concat",

View File

@@ -0,0 +1 @@
5a2307d0f2c5b650c6858e2b9b57b335a59946ff

View File

@@ -0,0 +1,10 @@
is_component_build = false
is_debug = false
target_cpu = "x64"
v8_enable_sandbox = false
v8_enable_backtrace = true
v8_enable_disassembler = true
v8_enable_object_print = true
dcheck_always_on = false
use_goma = false
v8_code_pointer_sandboxing = false

View File

@@ -0,0 +1,127 @@
diff --git a/src/builtins/builtins-array.cc b/src/builtins/builtins-array.cc
index ea45a7ada6b..4ed66c8113f 100644
--- a/src/builtins/builtins-array.cc
+++ b/src/builtins/builtins-array.cc
@@ -407,6 +407,46 @@ BUILTIN(ArrayPush) {
return *isolate->factory()->NewNumberFromUint((new_length));
}
+BUILTIN(ArrayOffByOne) {
+ HandleScope scope(isolate);
+ Factory *factory = isolate->factory();
+ Handle<Object> receiver = args.receiver();
+
+ if (!IsJSArray(*receiver) || !HasOnlySimpleReceiverElements(isolate, Cast<JSArray>(*receiver))) {
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly,
+ factory->NewStringFromAsciiChecked("Nope")));
+ }
+
+ Handle<JSArray> array = Cast<JSArray>(receiver);
+
+ ElementsKind kind = array->GetElementsKind();
+
+ if (kind != PACKED_DOUBLE_ELEMENTS) {
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly,
+ factory->NewStringFromAsciiChecked("Need an array of double numbers")));
+ }
+
+ if (args.length() > 2) {
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly,
+ factory->NewStringFromAsciiChecked("Too many arguments")));
+ }
+
+ Handle<FixedDoubleArray> elements(Cast<FixedDoubleArray>(array->elements()), isolate);
+ uint32_t len = static_cast<uint32_t>(Object::NumberValue(array->length()));
+ if (args.length() == 1) { // read mode
+ return *(isolate->factory()->NewNumber(elements->get_scalar(len)));
+ } else { // write mode
+ Handle<Object> value = args.at(1);
+ if (!IsNumber(*value)) {
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly,
+ factory->NewStringFromAsciiChecked("Need a number argument")));
+ }
+ double num = static_cast<double>(Object::NumberValue(*value));
+ elements->set(len, num);
+ return ReadOnlyRoots(isolate).undefined_value();
+ }
+}
+
namespace {
V8_WARN_UNUSED_RESULT Tagged<Object> GenericArrayPop(Isolate* isolate,
diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h
index 78cbf8874ed..8a0bd959a29 100644
--- a/src/builtins/builtins-definitions.h
+++ b/src/builtins/builtins-definitions.h
@@ -394,6 +394,7 @@ namespace internal {
ArraySingleArgumentConstructor) \
TFC(ArrayNArgumentsConstructor, ArrayNArgumentsConstructor) \
CPP(ArrayConcat) \
+ CPP(ArrayOffByOne) \
/* ES6 #sec-array.prototype.fill */ \
CPP(ArrayPrototypeFill) \
/* ES7 #sec-array.prototype.includes */ \
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index 9a346d134b9..ce31f92b876 100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -1937,6 +1937,8 @@ Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) {
return Type::Receiver();
case Builtin::kArrayUnshift:
return t->cache_->kPositiveSafeInteger;
+ case Builtin::kArrayOffByOne:
+ return Type::Receiver();
// ArrayBuffer functions.
case Builtin::kArrayBufferIsView:
diff --git a/src/d8/d8.cc b/src/d8/d8.cc
index facf0d86d79..382c015bc48 100644
--- a/src/d8/d8.cc
+++ b/src/d8/d8.cc
@@ -3364,7 +3364,7 @@ Local<FunctionTemplate> Shell::CreateNodeTemplates(
Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
- global_template->Set(Symbol::GetToStringTag(isolate),
+/* global_template->Set(Symbol::GetToStringTag(isolate),
String::NewFromUtf8Literal(isolate, "global"));
global_template->Set(isolate, "version",
FunctionTemplate::New(isolate, Version));
@@ -3385,13 +3385,13 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
global_template->Set(isolate, "readline",
FunctionTemplate::New(isolate, ReadLine));
global_template->Set(isolate, "load",
- FunctionTemplate::New(isolate, ExecuteFile));
+ FunctionTemplate::New(isolate, ExecuteFile));*/
global_template->Set(isolate, "setTimeout",
FunctionTemplate::New(isolate, SetTimeout));
// Some Emscripten-generated code tries to call 'quit', which in turn would
// call C's exit(). This would lead to memory leaks, because there is no way
// we can terminate cleanly then, so we need a way to hide 'quit'.
- if (!options.omit_quit) {
+/* if (!options.omit_quit) {
global_template->Set(isolate, "quit", FunctionTemplate::New(isolate, Quit));
}
global_template->Set(isolate, "testRunner",
@@ -3410,7 +3410,7 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
if (i::v8_flags.expose_async_hooks) {
global_template->Set(isolate, "async_hooks",
Shell::CreateAsyncHookTemplate(isolate));
- }
+ }*/
return global_template;
}
diff --git a/src/init/bootstrapper.cc b/src/init/bootstrapper.cc
index 48249695b7b..99dc014c13c 100644
--- a/src/init/bootstrapper.cc
+++ b/src/init/bootstrapper.cc
@@ -2533,6 +2533,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(isolate_, proto, "at", Builtin::kArrayPrototypeAt, 1,
true);
+ SimpleInstallFunction(isolate_, proto, "offByOne",
+ Builtin::kArrayOffByOne, 1, false);
SimpleInstallFunction(isolate_, proto, "concat",
Builtin::kArrayPrototypeConcat, 1, false);
SimpleInstallFunction(isolate_, proto, "copyWithin",

View File

@@ -0,0 +1 @@
5a2307d0f2c5b650c6858e2b9b57b335a59946ff

View File

@@ -0,0 +1,10 @@
is_component_build = false
is_debug = false
target_cpu = "x64"
v8_enable_sandbox = false
v8_enable_backtrace = true
v8_enable_disassembler = true
v8_enable_object_print = true
dcheck_always_on = false
use_goma = false
v8_code_pointer_sandboxing = false

View File

@@ -0,0 +1,134 @@
diff --git a/src/builtins/builtins-array.cc b/src/builtins/builtins-array.cc
index ea45a7ada6b..d450412f3e6 100644
--- a/src/builtins/builtins-array.cc
+++ b/src/builtins/builtins-array.cc
@@ -407,6 +407,53 @@ BUILTIN(ArrayPush) {
return *isolate->factory()->NewNumberFromUint((new_length));
}
+BUILTIN(ArrayFunctionMap) {
+ HandleScope scope(isolate);
+ Factory *factory = isolate->factory();
+ Handle<Object> receiver = args.receiver();
+
+ if (!IsJSArray(*receiver) || !HasOnlySimpleReceiverElements(isolate, Cast<JSArray>(*receiver))) {
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly,
+ factory->NewStringFromAsciiChecked("Nope")));
+ }
+
+ Handle<JSArray> array = Cast<JSArray>(receiver);
+
+ ElementsKind kind = array->GetElementsKind();
+
+ if (kind != PACKED_DOUBLE_ELEMENTS) {
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly,
+ factory->NewStringFromAsciiChecked("Need an array of double numbers")));
+ }
+
+ if (args.length() != 2) {
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly,
+ factory->NewStringFromAsciiChecked("Need exactly one argument")));
+ }
+
+ uint32_t len = static_cast<uint32_t>(Object::NumberValue(array->length()));
+
+ Handle<Object> func_obj = args.at(1);
+ if (!IsJSFunction(*func_obj)) {
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly,
+ factory->NewStringFromAsciiChecked("The argument must be a function")));
+ }
+
+ for (uint32_t i = 0; i < len; i++) {
+ double elem = Cast<FixedDoubleArray>(array->elements())->get_scalar(i);
+ Handle<Object> elem_handle = factory->NewHeapNumber(elem);
+ Handle<Object> result = Execution::Call(isolate, func_obj, array, 1, &elem_handle).ToHandleChecked();
+ if (!IsNumber(*result)) {
+ THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kPlaceholderOnly,
+ factory->NewStringFromAsciiChecked("The function must return a number")));
+ }
+ double result_value = static_cast<double>(Object::NumberValue(*result));
+ Cast<FixedDoubleArray>(array->elements())->set(i, result_value);
+ }
+
+ return ReadOnlyRoots(isolate).undefined_value();
+}
+
namespace {
V8_WARN_UNUSED_RESULT Tagged<Object> GenericArrayPop(Isolate* isolate,
diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h
index 78cbf8874ed..ede2775903e 100644
--- a/src/builtins/builtins-definitions.h
+++ b/src/builtins/builtins-definitions.h
@@ -394,6 +394,7 @@ namespace internal {
ArraySingleArgumentConstructor) \
TFC(ArrayNArgumentsConstructor, ArrayNArgumentsConstructor) \
CPP(ArrayConcat) \
+ CPP(ArrayFunctionMap) \
/* ES6 #sec-array.prototype.fill */ \
CPP(ArrayPrototypeFill) \
/* ES7 #sec-array.prototype.includes */ \
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index 9a346d134b9..33cf2d2edad 100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -1937,6 +1937,8 @@ Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) {
return Type::Receiver();
case Builtin::kArrayUnshift:
return t->cache_->kPositiveSafeInteger;
+ case Builtin::kArrayFunctionMap:
+ return Type::Receiver();
// ArrayBuffer functions.
case Builtin::kArrayBufferIsView:
diff --git a/src/d8/d8.cc b/src/d8/d8.cc
index facf0d86d79..382c015bc48 100644
--- a/src/d8/d8.cc
+++ b/src/d8/d8.cc
@@ -3364,7 +3364,7 @@ Local<FunctionTemplate> Shell::CreateNodeTemplates(
Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
- global_template->Set(Symbol::GetToStringTag(isolate),
+/* global_template->Set(Symbol::GetToStringTag(isolate),
String::NewFromUtf8Literal(isolate, "global"));
global_template->Set(isolate, "version",
FunctionTemplate::New(isolate, Version));
@@ -3385,13 +3385,13 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
global_template->Set(isolate, "readline",
FunctionTemplate::New(isolate, ReadLine));
global_template->Set(isolate, "load",
- FunctionTemplate::New(isolate, ExecuteFile));
+ FunctionTemplate::New(isolate, ExecuteFile));*/
global_template->Set(isolate, "setTimeout",
FunctionTemplate::New(isolate, SetTimeout));
// Some Emscripten-generated code tries to call 'quit', which in turn would
// call C's exit(). This would lead to memory leaks, because there is no way
// we can terminate cleanly then, so we need a way to hide 'quit'.
- if (!options.omit_quit) {
+/* if (!options.omit_quit) {
global_template->Set(isolate, "quit", FunctionTemplate::New(isolate, Quit));
}
global_template->Set(isolate, "testRunner",
@@ -3410,7 +3410,7 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
if (i::v8_flags.expose_async_hooks) {
global_template->Set(isolate, "async_hooks",
Shell::CreateAsyncHookTemplate(isolate));
- }
+ }*/
return global_template;
}
diff --git a/src/init/bootstrapper.cc b/src/init/bootstrapper.cc
index 48249695b7b..5e76e66bc15 100644
--- a/src/init/bootstrapper.cc
+++ b/src/init/bootstrapper.cc
@@ -2533,6 +2533,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(isolate_, proto, "at", Builtin::kArrayPrototypeAt, 1,
true);
+ SimpleInstallFunction(isolate_, proto, "functionMap",
+ Builtin::kArrayFunctionMap, 1, false);
SimpleInstallFunction(isolate_, proto, "concat",
Builtin::kArrayPrototypeConcat, 1, false);
SimpleInstallFunction(isolate_, proto, "copyWithin",