Commit 9323085a authored by Manos Koukoutos's avatar Manos Koukoutos Committed by V8 LUCI CQ

[wasm-gc] Add ArrayTooLarge trap

This will be thrown during array allocations if the requested size is
larger than kV8MaxWasmArrayLength.

Additional changes:
- In test-gc.cc, add the possibility to check against the trap message
  in CheckHasThrown.
- Small reorganization of WasmGCTester in test-gc.cc.

Bug: v8:7748
Change-Id: I6f74b525bd7087fcc66f43c451ef130df022b0f9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2922247Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74867}
parent 5895436b
...@@ -405,6 +405,7 @@ extern enum MessageTemplate { ...@@ -405,6 +405,7 @@ extern enum MessageTemplate {
kWasmTrapNullDereference, kWasmTrapNullDereference,
kWasmTrapIllegalCast, kWasmTrapIllegalCast,
kWasmTrapArrayOutOfBounds, kWasmTrapArrayOutOfBounds,
kWasmTrapArrayTooLarge,
kWeakRefsRegisterTargetAndHoldingsMustNotBeSame, kWeakRefsRegisterTargetAndHoldingsMustNotBeSame,
kWeakRefsRegisterTargetMustBeObject, kWeakRefsRegisterTargetMustBeObject,
kWeakRefsUnregisterTokenMustBeObject, kWeakRefsUnregisterTokenMustBeObject,
......
...@@ -524,4 +524,8 @@ builtin ThrowWasmTrapIllegalCast(): JSAny { ...@@ -524,4 +524,8 @@ builtin ThrowWasmTrapIllegalCast(): JSAny {
builtin ThrowWasmTrapArrayOutOfBounds(): JSAny { builtin ThrowWasmTrapArrayOutOfBounds(): JSAny {
tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapArrayOutOfBounds)); tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapArrayOutOfBounds));
} }
builtin ThrowWasmTrapArrayTooLarge(): JSAny {
tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapArrayTooLarge));
}
} }
...@@ -1693,7 +1693,8 @@ enum class LoadSensitivity { ...@@ -1693,7 +1693,8 @@ enum class LoadSensitivity {
V(TrapRethrowNull) \ V(TrapRethrowNull) \
V(TrapNullDereference) \ V(TrapNullDereference) \
V(TrapIllegalCast) \ V(TrapIllegalCast) \
V(TrapArrayOutOfBounds) V(TrapArrayOutOfBounds) \
V(TrapArrayTooLarge)
enum KeyedAccessLoadMode { enum KeyedAccessLoadMode {
STANDARD_LOAD, STANDARD_LOAD,
......
...@@ -576,6 +576,7 @@ namespace internal { ...@@ -576,6 +576,7 @@ namespace internal {
T(WasmTrapNullDereference, "dereferencing a null pointer") \ T(WasmTrapNullDereference, "dereferencing a null pointer") \
T(WasmTrapIllegalCast, "illegal cast") \ T(WasmTrapIllegalCast, "illegal cast") \
T(WasmTrapArrayOutOfBounds, "array element access out of bounds") \ T(WasmTrapArrayOutOfBounds, "array element access out of bounds") \
T(WasmTrapArrayTooLarge, "requested new array is too large") \
T(WasmExceptionError, "wasm exception") \ T(WasmExceptionError, "wasm exception") \
/* Asm.js validation related */ \ /* Asm.js validation related */ \
T(AsmJsInvalid, "Invalid asm.js: %") \ T(AsmJsInvalid, "Invalid asm.js: %") \
......
...@@ -5572,7 +5572,7 @@ Node* WasmGraphBuilder::ArrayNewWithRtt(uint32_t array_index, ...@@ -5572,7 +5572,7 @@ Node* WasmGraphBuilder::ArrayNewWithRtt(uint32_t array_index,
Node* length, Node* initial_value, Node* length, Node* initial_value,
Node* rtt, Node* rtt,
wasm::WasmCodePosition position) { wasm::WasmCodePosition position) {
TrapIfFalse(wasm::kTrapArrayOutOfBounds, TrapIfFalse(wasm::kTrapArrayTooLarge,
gasm_->Uint32LessThanOrEqual( gasm_->Uint32LessThanOrEqual(
length, gasm_->Uint32Constant(wasm::kV8MaxWasmArrayLength)), length, gasm_->Uint32Constant(wasm::kV8MaxWasmArrayLength)),
position); position);
......
...@@ -4946,7 +4946,7 @@ class LiftoffCompiler { ...@@ -4946,7 +4946,7 @@ class LiftoffCompiler {
LiftoffRegister length = LiftoffRegister length =
__ LoadToRegister(__ cache_state()->stack_state.end()[-2], {}); __ LoadToRegister(__ cache_state()->stack_state.end()[-2], {});
Label* trap_label = Label* trap_label =
AddOutOfLineTrap(decoder, WasmCode::kThrowWasmTrapArrayOutOfBounds); AddOutOfLineTrap(decoder, WasmCode::kThrowWasmTrapArrayTooLarge);
__ emit_i32_cond_jumpi(kUnsignedGreaterThan, trap_label, length.gp(), __ emit_i32_cond_jumpi(kUnsignedGreaterThan, trap_label, length.gp(),
static_cast<int>(wasm::kV8MaxWasmArrayLength)); static_cast<int>(wasm::kV8MaxWasmArrayLength));
} }
......
...@@ -111,48 +111,25 @@ class WasmGCTester { ...@@ -111,48 +111,25 @@ class WasmGCTester {
instance_ = maybe_instance.ToHandleChecked(); instance_ = maybe_instance.ToHandleChecked();
} }
void CallFunctionImpl(uint32_t function_index, const FunctionSig* sig,
CWasmArgumentsPacker* packer) {
WasmCodeRefScope scope;
NativeModule* native_module = instance_->module_object().native_module();
WasmCode* code = native_module->GetCode(function_index);
Address wasm_call_target = code->instruction_start();
Handle<Object> object_ref = instance_;
Handle<Code> c_wasm_entry =
compiler::CompileCWasmEntry(isolate_, sig, native_module->module());
Execution::CallWasm(isolate_, c_wasm_entry, wasm_call_target, object_ref,
packer->argv());
}
void CheckResult(uint32_t function_index, int32_t expected) { void CheckResult(uint32_t function_index, int32_t expected) {
FunctionSig* sig = sigs.i_v(); const FunctionSig* sig = sigs.i_v();
DCHECK(*sig == *instance_->module()->functions[function_index].sig); DCHECK(*sig == *instance_->module()->functions[function_index].sig);
CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig)); CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig));
CallFunctionImpl(function_index, sig, &packer); CheckResultImpl(function_index, sig, &packer, expected);
CHECK(!isolate_->has_pending_exception());
packer.Reset();
CHECK_EQ(expected, packer.Pop<int32_t>());
} }
void CheckResult(uint32_t function_index, int32_t expected, int32_t arg) { void CheckResult(uint32_t function_index, int32_t expected, int32_t arg) {
FunctionSig* sig = sigs.i_i(); const FunctionSig* sig = sigs.i_i();
DCHECK(*sig == *instance_->module()->functions[function_index].sig); DCHECK(*sig == *instance_->module()->functions[function_index].sig);
CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig)); CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig));
packer.Push(arg); packer.Push(arg);
CallFunctionImpl(function_index, sig, &packer); CheckResultImpl(function_index, sig, &packer, expected);
if (isolate_->has_pending_exception()) {
Handle<String> message =
ErrorUtils::ToString(isolate_,
handle(isolate_->pending_exception(), isolate_))
.ToHandleChecked();
FATAL("%s", message->ToCString().get());
}
packer.Reset();
CHECK_EQ(expected, packer.Pop<int32_t>());
} }
MaybeHandle<Object> GetResultObject(uint32_t function_index) { MaybeHandle<Object> GetResultObject(uint32_t function_index) {
const FunctionSig* sig = instance_->module()->functions[function_index].sig; const FunctionSig* sig = instance_->module()->functions[function_index].sig;
DCHECK_EQ(sig->parameter_count(), 0);
DCHECK_EQ(sig->return_count(), 1);
CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig)); CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig));
CallFunctionImpl(function_index, sig, &packer); CallFunctionImpl(function_index, sig, &packer);
CHECK(!isolate_->has_pending_exception()); CHECK(!isolate_->has_pending_exception());
...@@ -163,6 +140,7 @@ class WasmGCTester { ...@@ -163,6 +140,7 @@ class WasmGCTester {
MaybeHandle<Object> GetResultObject(uint32_t function_index, int32_t arg) { MaybeHandle<Object> GetResultObject(uint32_t function_index, int32_t arg) {
const FunctionSig* sig = instance_->module()->functions[function_index].sig; const FunctionSig* sig = instance_->module()->functions[function_index].sig;
DCHECK_EQ(sig->parameter_count(), 1); DCHECK_EQ(sig->parameter_count(), 1);
DCHECK_EQ(sig->return_count(), 1);
DCHECK(sig->parameters()[0] == kWasmI32); DCHECK(sig->parameters()[0] == kWasmI32);
CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig)); CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig));
packer.Push(arg); packer.Push(arg);
...@@ -172,22 +150,21 @@ class WasmGCTester { ...@@ -172,22 +150,21 @@ class WasmGCTester {
return Handle<Object>(Object(packer.Pop<Address>()), isolate_); return Handle<Object>(Object(packer.Pop<Address>()), isolate_);
} }
void CheckHasThrown(uint32_t function_index) { void CheckHasThrown(uint32_t function_index, const char* expected = "") {
const FunctionSig* sig = instance_->module()->functions[function_index].sig; const FunctionSig* sig = instance_->module()->functions[function_index].sig;
DCHECK_EQ(sig->parameter_count(), 0);
CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig)); CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig));
CallFunctionImpl(function_index, sig, &packer); CheckHasThrownImpl(function_index, sig, &packer, expected);
CHECK(isolate_->has_pending_exception());
isolate_->clear_pending_exception();
} }
void CheckHasThrown(uint32_t function_index, int32_t arg) { void CheckHasThrown(uint32_t function_index, int32_t arg,
FunctionSig* sig = sigs.i_i(); const char* expected = "") {
DCHECK(*sig == *instance_->module()->functions[function_index].sig); const FunctionSig* sig = instance_->module()->functions[function_index].sig;
DCHECK_EQ(sig->parameter_count(), 1);
DCHECK(sig->parameters()[0] == kWasmI32);
CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig)); CWasmArgumentsPacker packer(CWasmArgumentsPacker::TotalSize(sig));
packer.Push(arg); packer.Push(arg);
CallFunctionImpl(function_index, sig, &packer); CheckHasThrownImpl(function_index, sig, &packer, expected);
CHECK(isolate_->has_pending_exception());
isolate_->clear_pending_exception();
} }
Handle<WasmInstanceObject> instance() { return instance_; } Handle<WasmInstanceObject> instance() { return instance_; }
...@@ -205,6 +182,46 @@ class WasmGCTester { ...@@ -205,6 +182,46 @@ class WasmGCTester {
const FlagScope<bool> flag_liftoff_only; const FlagScope<bool> flag_liftoff_only;
const FlagScope<bool> flag_tierup; const FlagScope<bool> flag_tierup;
void CheckResultImpl(uint32_t function_index, const FunctionSig* sig,
CWasmArgumentsPacker* packer, int32_t expected) {
CallFunctionImpl(function_index, sig, packer);
if (isolate_->has_pending_exception()) {
Handle<String> message =
ErrorUtils::ToString(isolate_,
handle(isolate_->pending_exception(), isolate_))
.ToHandleChecked();
FATAL("%s", message->ToCString().get());
}
packer->Reset();
CHECK_EQ(expected, packer->Pop<int32_t>());
}
void CheckHasThrownImpl(uint32_t function_index, const FunctionSig* sig,
CWasmArgumentsPacker* packer, const char* expected) {
CallFunctionImpl(function_index, sig, packer);
CHECK(isolate_->has_pending_exception());
Handle<String> message =
ErrorUtils::ToString(isolate_,
handle(isolate_->pending_exception(), isolate_))
.ToHandleChecked();
std::string message_str(message->ToCString().get());
CHECK_NE(message_str.find(expected), std::string::npos);
isolate_->clear_pending_exception();
}
void CallFunctionImpl(uint32_t function_index, const FunctionSig* sig,
CWasmArgumentsPacker* packer) {
WasmCodeRefScope scope;
NativeModule* native_module = instance_->module_object().native_module();
WasmCode* code = native_module->GetCode(function_index);
Address wasm_call_target = code->instruction_start();
Handle<Object> object_ref = instance_;
Handle<Code> c_wasm_entry =
compiler::CompileCWasmEntry(isolate_, sig, native_module->module());
Execution::CallWasm(isolate_, c_wasm_entry, wasm_call_target, object_ref,
packer->argv());
}
v8::internal::AccountingAllocator allocator; v8::internal::AccountingAllocator allocator;
Zone zone_; Zone zone_;
WasmModuleBuilder builder_; WasmModuleBuilder builder_;
...@@ -813,7 +830,7 @@ WASM_COMPILED_EXEC_TEST(WasmBasicArray) { ...@@ -813,7 +830,7 @@ WASM_COMPILED_EXEC_TEST(WasmBasicArray) {
CHECK(Handle<WasmArray>::cast(large_result)->Size() > CHECK(Handle<WasmArray>::cast(large_result)->Size() >
kMaxRegularHeapObjectSize); kMaxRegularHeapObjectSize);
tester.CheckHasThrown(kAllocateTooLarge); tester.CheckHasThrown(kAllocateTooLarge, "requested new array is too large");
} }
WASM_COMPILED_EXEC_TEST(WasmPackedArrayU) { WASM_COMPILED_EXEC_TEST(WasmPackedArrayU) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment