diff --git a/ecmascript/compiler/builtins/builtins_proxy_stub_builder.cpp b/ecmascript/compiler/builtins/builtins_proxy_stub_builder.cpp index e969261d464fe6dee4a2e32c068c3ed1ee95489a..95943e95353095516281384b8369ea1ce6b12e20 100644 --- a/ecmascript/compiler/builtins/builtins_proxy_stub_builder.cpp +++ b/ecmascript/compiler/builtins/builtins_proxy_stub_builder.cpp @@ -178,7 +178,8 @@ GateRef BuiltinsProxyStubBuilder::GetProperty(GateRef proxy, GateRef key, GateRe { auto env = GetEnvironment(); DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); - Label callExit(env); + Label stackOverflow(env); + Label dispatch(env); Label checkGetTrapResult(env); Label exit(env); Label handlerIsNull(env); @@ -186,6 +187,14 @@ GateRef BuiltinsProxyStubBuilder::GetProperty(GateRef proxy, GateRef key, GateRe Label slowPath(env); Label trapIsCallable(env); Label trapFastPath(env); + BRANCH_UNLIKELY(CheckStackOverflow(glue_), &stackOverflow, &dispatch); + Bind(&stackOverflow); + { + CallRuntimeWithGlobalEnv(glue_, GetCurrentGlobalEnv(), RTSTUB_ID(ThrowStackOverflowException), {}); + result = Exception(); + Jump(&exit); + } + Bind(&dispatch); GateRef handler = GetHandler(glue_, proxy); BRANCH(TaggedIsNull(handler), &handlerIsNull, &handlerIsNotNull); Bind(&handlerIsNull); @@ -201,6 +210,15 @@ GateRef BuiltinsProxyStubBuilder::GetProperty(GateRef proxy, GateRef key, GateRe GateRef name = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::GET_STRING_INDEX); GateRef trap = GetPropertyByName(glue_, handler, name); + Label isPendingException(env); + Label noPendingException(env); + BRANCH_UNLIKELY(HasPendingException(glue_), &isPendingException, &noPendingException); + Bind(&isPendingException); + { + result = Exception(); + Jump(&exit); + } + Bind(&noPendingException); BRANCH(TaggedIsHeapObject(trap), &trapFastPath, &slowPath); Bind(&trapFastPath); { @@ -236,8 +254,9 @@ GateRef BuiltinsProxyStubBuilder::SetProperty(GateRef proxy, GateRef key, GateRe { auto env = GetEnvironment(); DEFVARIABLE(result, VariableType::JS_ANY(), TaggedTrue()); + Label stackOverflow(env); + Label dispatch(env); Label trapResultIsFalse(env); - Label callExit(env); Label checkSetTrapResult(env); Label exit(env); Label handlerIsNull(env); @@ -245,6 +264,14 @@ GateRef BuiltinsProxyStubBuilder::SetProperty(GateRef proxy, GateRef key, GateRe Label slowPath(env); Label trapIsCallable(env); Label trapFastPath(env); + BRANCH_UNLIKELY(CheckStackOverflow(glue_), &stackOverflow, &dispatch); + Bind(&stackOverflow); + { + CallRuntimeWithGlobalEnv(glue_, GetCurrentGlobalEnv(), RTSTUB_ID(ThrowStackOverflowException), {}); + result = TaggedFalse(); + Jump(&exit); + } + Bind(&dispatch); GateRef handler = GetHandler(glue_, proxy); BRANCH(TaggedIsNull(handler), &handlerIsNull, &handlerIsNotNull); Bind(&handlerIsNull); @@ -260,6 +287,15 @@ GateRef BuiltinsProxyStubBuilder::SetProperty(GateRef proxy, GateRef key, GateRe GateRef name = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::SET_STRING_INDEX); GateRef trap = GetPropertyByName(glue_, handler, name); + Label isPendingException(env); + Label noPendingException(env); + BRANCH_UNLIKELY(HasPendingException(glue_), &isPendingException, &noPendingException); + Bind(&isPendingException); + { + result = TaggedFalse(); + Jump(&exit); + } + Bind(&noPendingException); BRANCH(TaggedIsHeapObject(trap), &trapFastPath, &slowPath); Bind(&trapFastPath); { diff --git a/ecmascript/compiler/stub_builder-inl.h b/ecmascript/compiler/stub_builder-inl.h index 90bf40f9f4e4fb56e07263499f889d9c49a12984..b76621439d965ffdb3c1427b6ef8deddf8fdf627 100644 --- a/ecmascript/compiler/stub_builder-inl.h +++ b/ecmascript/compiler/stub_builder-inl.h @@ -55,6 +55,24 @@ inline int StubBuilder::NextVariableId() return env_->NextVariableId(); } +inline GateRef StubBuilder::ReadSp() +{ + return env_->GetBuilder()->ReadSp(); +} + +inline GateRef StubBuilder::CheckStackOverflow(GateRef glue) +{ + GateRef allowCrossThreadExecution = LoadPrimitive(VariableType::BOOL(), glue, + IntPtr(JSThread::GlueData::GetAllowCrossThreadExecutionOffset(env_->IsArch32Bit()))); + GateRef sp = ReadSp(); + GateRef stackLimit = LoadPrimitive(VariableType::INT64(), glue, + IntPtr(JSThread::GlueData::GetStackLimitOffset(env_->IsArch32Bit()))); + return LogicAndBuilder(env_) + .And(BoolNot(allowCrossThreadExecution)) + .And(Int64UnsignedLessThanOrEqual(sp, stackLimit)) + .Done(); +} + inline GateRef StubBuilder::Int8(int8_t value) { return env_->GetBuilder()->Int8(value); diff --git a/ecmascript/compiler/stub_builder.h b/ecmascript/compiler/stub_builder.h index a909b492ca9d3d7ddb2f7f7a2846928b78b7300f..c81326f13859699625e0224cebf4f34656dd4f75 100644 --- a/ecmascript/compiler/stub_builder.h +++ b/ecmascript/compiler/stub_builder.h @@ -132,6 +132,8 @@ public: { globalEnv_ = globalEnv; } + GateRef ReadSp(); + GateRef CheckStackOverflow(GateRef glue); int NextVariableId(); // constant GateRef Int8(int8_t value); diff --git a/ecmascript/stubs/runtime_stubs.cpp b/ecmascript/stubs/runtime_stubs.cpp index 4f213f59f51f88a4faf33212bbd8a087536a6d01..2669d3090b89820bf6510e3a5071434a997fc8ac 100644 --- a/ecmascript/stubs/runtime_stubs.cpp +++ b/ecmascript/stubs/runtime_stubs.cpp @@ -2771,6 +2771,8 @@ DEF_RUNTIME_STUBS(ThrowStackOverflowException) // Multi-thread could cause stack-overflow-check failed too, // so check thread here to distinguish it with the actual stack overflow. ecmaVm->CheckThread(); + LOG_ECMA(ERROR) << "Stack overflow! current:" << thread->GetCurrentStackPosition() + << " limit:" << thread->GetStackLimit(); ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle error = factory->GetJSError(ErrorType::RANGE_ERROR, "Stack overflow!", StackCheck::NO); if (LIKELY(!thread->HasPendingException())) { diff --git a/test/moduletest/proxyget/expect_output.txt b/test/moduletest/proxyget/expect_output.txt index 42df7d4f1888669a36d2ea40648898df065942f4..d7cc898abf998bbe739582f97a32651efb359a92 100644 --- a/test/moduletest/proxyget/expect_output.txt +++ b/test/moduletest/proxyget/expect_output.txt @@ -14,3 +14,4 @@ $99 undefined TypeError: obj is not Callable +RangeError: Stack overflow! diff --git a/test/moduletest/proxyget/proxyget.js b/test/moduletest/proxyget/proxyget.js index 3a7e251e98168258eef48abbe335e4760403cc37..a715cb80907c32df558d5a834a751ed7b8201fb9 100644 --- a/test/moduletest/proxyget/proxyget.js +++ b/test/moduletest/proxyget/proxyget.js @@ -189,4 +189,18 @@ function test9() } test9(); +function test10() +{ + let target = { a: 1 }; + const handler = {}; + handler.__proto__ = new Proxy(target, handler); + try { + handler.__proto__ = new Proxy(target, handler); + } catch (error) { + assert_equal(error instanceof RangeError, true); + print(error); + } +} +test10(); + test_end();