Diff
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (201494 => 201495)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2016-05-29 04:47:41 UTC (rev 201494)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2016-05-29 19:01:36 UTC (rev 201495)
@@ -845,6 +845,9 @@
yarr/YarrSyntaxChecker.cpp
)
+# Extra flags for compile sources can go here.
+set_source_files_properties(runtime/ProxyObject.cpp PROPERTIES COMPILE_FLAGS -fno-optimize-sibling-calls)
+
set(_javascript_Core_OBJECT_LUT_SOURCES
runtime/ArrayConstructor.cpp
runtime/ArrayIteratorPrototype.cpp
Modified: trunk/Source/_javascript_Core/ChangeLog (201494 => 201495)
--- trunk/Source/_javascript_Core/ChangeLog 2016-05-29 04:47:41 UTC (rev 201494)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-05-29 19:01:36 UTC (rev 201495)
@@ -1,3 +1,88 @@
+2016-05-29 Saam barati <[email protected]>
+
+ Stack overflow crashes with deep or cyclic proxy prototype chains
+ https://bugs.webkit.org/show_bug.cgi?id=157087
+
+ Reviewed by Filip Pizlo and Mark Lam.
+
+ Because a Proxy can call back into the JS runtime in arbitrary
+ ways, we may have effectively cyclic prototype chains and property lookups
+ by using a Proxy. We may also have arbitrarily long Proxy chains
+ where we call into a C frame for each link in the Proxy chain.
+ This means that every Proxy hook must be aware that it can stack overflow.
+ Before, only certain hooks were aware of this fact. That was a bug,
+ all hooks must assume they can stack overflow.
+
+ Also, because we may have effectively cyclic prototype chains, we
+ compile ProxyObject.cpp with -fno-optimize-sibling-calls. This prevents
+ tail call optimization from happening on any of the calls from
+ ProxyObject.cpp. We do this because we rely on the machine stack
+ growing for throwing a stack overflow error. It's better for developers
+ to be able to see a stack overflow error than to have their program
+ infinite loop because the compiler performed TCO.
+
+ This patch also fixes a couple call sites of various methods
+ where we didn't check for an exception.
+
+ * CMakeLists.txt:
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * interpreter/Interpreter.cpp:
+ (JSC::sizeOfVarargs):
+ * runtime/InternalFunction.cpp:
+ (JSC::InternalFunction::createSubclassStructure):
+ * runtime/JSArray.h:
+ (JSC::getLength):
+ * runtime/ObjectPrototype.cpp:
+ (JSC::objectProtoFuncToString):
+ * runtime/ProxyObject.cpp:
+ (JSC::performProxyGet):
+ (JSC::ProxyObject::performInternalMethodGetOwnProperty):
+ (JSC::ProxyObject::performHasProperty):
+ (JSC::ProxyObject::getOwnPropertySlotCommon):
+ (JSC::ProxyObject::performPut):
+ (JSC::performProxyCall):
+ (JSC::performProxyConstruct):
+ (JSC::ProxyObject::performDelete):
+ (JSC::ProxyObject::performPreventExtensions):
+ (JSC::ProxyObject::performIsExtensible):
+ (JSC::ProxyObject::performDefineOwnProperty):
+ (JSC::ProxyObject::performGetOwnPropertyNames):
+ (JSC::ProxyObject::getOwnPropertyNames):
+ (JSC::ProxyObject::getPropertyNames):
+ (JSC::ProxyObject::getOwnNonIndexPropertyNames):
+ (JSC::ProxyObject::performSetPrototype):
+ (JSC::ProxyObject::performGetPrototype):
+ * runtime/ProxyObject.h:
+ (JSC::ProxyObject::create):
+ * tests/stress/proxy-stack-overflow-exceptions.js: Added.
+ (shouldThrowStackOverflow):
+ (const.emptyFunction):
+ (makeLongProxyChain):
+ (shouldThrowStackOverflow.longProxyChain):
+ (shouldThrowStackOverflow.effecivelyCyclicProxyProtoChain1):
+ (shouldThrowStackOverflow.effecivelyCyclicProxyProtoChain2):
+ (shouldThrowStackOverflow.effecivelyCyclicProxyProtoChain3):
+ (shouldThrowStackOverflow.longProxyChainBind):
+ (shouldThrowStackOverflow.longProxyChainPropertyAccess):
+ (shouldThrowStackOverflow.longProxyChainReflectConstruct):
+ (shouldThrowStackOverflow.longProxyChainReflectSet):
+ (shouldThrowStackOverflow.longProxyChainReflectOwnKeys):
+ (shouldThrowStackOverflow.longProxyChainGetPrototypeOf):
+ (shouldThrowStackOverflow.longProxyChainSetPrototypeOf):
+ (shouldThrowStackOverflow.longProxyChainGetOwnPropertyDescriptor):
+ (shouldThrowStackOverflow.longProxyChainDefineProperty):
+ (shouldThrowStackOverflow.longProxyChainIsExtensible):
+ (shouldThrowStackOverflow.longProxyChainPreventExtensions):
+ (shouldThrowStackOverflow.longProxyChainDeleteProperty):
+ (shouldThrowStackOverflow.longProxyChainWithScope):
+ (shouldThrowStackOverflow.longProxyChainWithScope2):
+ (shouldThrowStackOverflow.longProxyChainWithScope3):
+ (shouldThrowStackOverflow.longProxyChainArrayPrototypePush):
+ (shouldThrowStackOverflow.longProxyChainWithScope4):
+ (shouldThrowStackOverflow.longProxyChainCall):
+ (shouldThrowStackOverflow.longProxyChainConstruct):
+ (shouldThrowStackOverflow.longProxyChainHas):
+
2016-05-28 Andreas Kling <[email protected]>
JSGlobalLexicalEnvironment leaks SegmentedVector due to lack of destructor.
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (201494 => 201495)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2016-05-29 04:47:41 UTC (rev 201494)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2016-05-29 19:01:36 UTC (rev 201495)
@@ -1288,7 +1288,7 @@
799EF7C41C56ED96002B0534 /* B3PCToOriginMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 799EF7C31C56ED96002B0534 /* B3PCToOriginMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
79B00CBC1C6AB07E0088C65D /* ProxyConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79B00CB81C6AB07E0088C65D /* ProxyConstructor.cpp */; };
79B00CBD1C6AB07E0088C65D /* ProxyConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 79B00CB91C6AB07E0088C65D /* ProxyConstructor.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 79B00CBE1C6AB07E0088C65D /* ProxyObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79B00CBA1C6AB07E0088C65D /* ProxyObject.cpp */; };
+ 79B00CBE1C6AB07E0088C65D /* ProxyObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79B00CBA1C6AB07E0088C65D /* ProxyObject.cpp */; settings = {COMPILER_FLAGS = "-fno-optimize-sibling-calls"; }; };
79B00CBF1C6AB07E0088C65D /* ProxyObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 79B00CBB1C6AB07E0088C65D /* ProxyObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
79C4B15D1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79C4B15B1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.cpp */; };
79C4B15E1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 79C4B15C1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (201494 => 201495)
--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp 2016-05-29 04:47:41 UTC (rev 201494)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp 2016-05-29 19:01:36 UTC (rev 201495)
@@ -218,7 +218,7 @@
length = jsCast<DirectArguments*>(cell)->length(callFrame);
break;
case ScopedArgumentsType:
- length =jsCast<ScopedArguments*>(cell)->length(callFrame);
+ length = jsCast<ScopedArguments*>(cell)->length(callFrame);
break;
case StringType:
callFrame->vm().throwException(callFrame, createInvalidFunctionApplyParameterError(callFrame, arguments));
@@ -226,8 +226,11 @@
default:
ASSERT(arguments.isObject());
length = getLength(callFrame, jsCast<JSObject*>(cell));
+ if (UNLIKELY(callFrame->hadException()))
+ return 0;
break;
}
+
if (length >= firstVarArgOffset)
length -= firstVarArgOffset;
Modified: trunk/Source/_javascript_Core/runtime/InternalFunction.cpp (201494 => 201495)
--- trunk/Source/_javascript_Core/runtime/InternalFunction.cpp 2016-05-29 04:47:41 UTC (rev 201494)
+++ trunk/Source/_javascript_Core/runtime/InternalFunction.cpp 2016-05-29 19:01:36 UTC (rev 201495)
@@ -109,16 +109,16 @@
return structure;
// Note, Reflect.construct might cause the profile to churn but we don't care.
- JSObject* prototype = jsDynamicCast<JSObject*>(newTarget.get(exec, exec->propertyNames().prototype));
- if (exec->hadException())
+ JSValue prototypeValue = newTarget.get(exec, exec->propertyNames().prototype);
+ if (UNLIKELY(vm.exception()))
return nullptr;
- if (prototype)
+ if (JSObject* prototype = jsDynamicCast<JSObject*>(prototypeValue))
return targetFunction->rareData(vm)->createInternalFunctionAllocationStructureFromBase(vm, prototype, baseClass);
} else {
- JSObject* prototype = jsDynamicCast<JSObject*>(newTarget.get(exec, exec->propertyNames().prototype));
- if (exec->hadException())
+ JSValue prototypeValue = newTarget.get(exec, exec->propertyNames().prototype);
+ if (UNLIKELY(vm.exception()))
return nullptr;
- if (prototype) {
+ if (JSObject* prototype = jsDynamicCast<JSObject*>(prototypeValue)) {
// This only happens if someone Reflect.constructs our builtin constructor with another builtin constructor as the new.target.
// Thus, we don't care about the cost of looking up the structure from our hash table every time.
return vm.prototypeMap.emptyStructureForPrototypeFromBaseStructure(prototype, baseClass);
Modified: trunk/Source/_javascript_Core/runtime/JSArray.h (201494 => 201495)
--- trunk/Source/_javascript_Core/runtime/JSArray.h 2016-05-29 04:47:41 UTC (rev 201494)
+++ trunk/Source/_javascript_Core/runtime/JSArray.h 2016-05-29 19:01:36 UTC (rev 201495)
@@ -352,7 +352,12 @@
{
if (isJSArray(obj))
return jsCast<JSArray*>(obj)->length();
- return obj->get(exec, exec->propertyNames().length).toUInt32(exec);
+
+ VM& vm = exec->vm();
+ JSValue lengthValue = obj->get(exec, vm.propertyNames->length);
+ if (UNLIKELY(vm.exception()))
+ return UINT_MAX;
+ return lengthValue.toUInt32(exec);
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/ObjectPrototype.cpp (201494 => 201495)
--- trunk/Source/_javascript_Core/runtime/ObjectPrototype.cpp 2016-05-29 04:47:41 UTC (rev 201494)
+++ trunk/Source/_javascript_Core/runtime/ObjectPrototype.cpp 2016-05-29 19:01:36 UTC (rev 201495)
@@ -282,6 +282,8 @@
PropertySlot toStringTagSlot(thisObject, PropertySlot::InternalMethodType::Get);
if (thisObject->getPropertySlot(exec, toStringTagSymbol, toStringTagSlot)) {
JSValue stringTag = toStringTagSlot.getValue(exec, toStringTagSymbol);
+ if (UNLIKELY(vm.exception()))
+ return JSValue::encode(JSValue());
if (stringTag.isString()) {
JSRopeString::RopeBuilder ropeBuilder(vm);
ropeBuilder.append(vm.smallStrings.objectStringStart());
Modified: trunk/Source/_javascript_Core/runtime/ProxyObject.cpp (201494 => 201495)
--- trunk/Source/_javascript_Core/runtime/ProxyObject.cpp 2016-05-29 04:47:41 UTC (rev 201494)
+++ trunk/Source/_javascript_Core/runtime/ProxyObject.cpp 2016-05-29 19:01:36 UTC (rev 201495)
@@ -34,6 +34,9 @@
#include "SlotVisitorInlines.h"
#include "StructureInlines.h"
+// Note that this file is compile with -fno-optimize-sibling-calls because we rely on the machine stack
+// growing larger for throwing OOM errors for when we have an effectively cyclic prototype chain.
+
namespace JSC {
STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(ProxyObject);
@@ -95,7 +98,7 @@
static EncodedJSValue performProxyGet(ExecState* exec, EncodedJSValue thisValue, PropertyName propertyName, JSObject* slotBase)
{
VM& vm = exec->vm();
- if (!vm.isSafeToRecurse()) {
+ if (UNLIKELY(!vm.isSafeToRecurse())) {
throwStackOverflowError(exec);
return JSValue::encode(JSValue());
}
@@ -155,6 +158,10 @@
bool ProxyObject::performInternalMethodGetOwnProperty(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
{
VM& vm = exec->vm();
+ if (UNLIKELY(!vm.isSafeToRecurse())) {
+ throwStackOverflowError(exec);
+ return false;
+ }
JSObject* target = this->target();
auto performDefaultGetOwnProperty = [&] {
@@ -257,6 +264,10 @@
bool ProxyObject::performHasProperty(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
{
VM& vm = exec->vm();
+ if (UNLIKELY(!vm.isSafeToRecurse())) {
+ throwStackOverflowError(exec);
+ return false;
+ }
JSObject* target = this->target();
slot.setValue(this, None, jsUndefined()); // Nobody should rely on our value, but be safe and protect against any bad actors reading our value.
@@ -318,6 +329,10 @@
bool ProxyObject::getOwnPropertySlotCommon(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
{
+ if (UNLIKELY(!exec->vm().isSafeToRecurse())) {
+ throwStackOverflowError(exec);
+ return false;
+ }
slot.disableCaching();
slot.setIsTaintedByProxy();
switch (slot.internalMethodType()) {
@@ -353,7 +368,7 @@
bool ProxyObject::performPut(ExecState* exec, JSValue putValue, JSValue thisValue, PropertyName propertyName, PerformDefaultPutFunction performDefaultPut)
{
VM& vm = exec->vm();
- if (!vm.isSafeToRecurse()) {
+ if (UNLIKELY(!vm.isSafeToRecurse())) {
throwStackOverflowError(exec);
return false;
}
@@ -445,6 +460,10 @@
static EncodedJSValue JSC_HOST_CALL performProxyCall(ExecState* exec)
{
VM& vm = exec->vm();
+ if (UNLIKELY(!vm.isSafeToRecurse())) {
+ throwStackOverflowError(exec);
+ return JSValue::encode(JSValue());
+ }
ProxyObject* proxy = jsCast<ProxyObject*>(exec->callee());
JSValue handlerValue = proxy->handler();
if (handlerValue.isNull())
@@ -490,6 +509,10 @@
static EncodedJSValue JSC_HOST_CALL performProxyConstruct(ExecState* exec)
{
VM& vm = exec->vm();
+ if (UNLIKELY(!vm.isSafeToRecurse())) {
+ throwStackOverflowError(exec);
+ return JSValue::encode(JSValue());
+ }
ProxyObject* proxy = jsCast<ProxyObject*>(exec->callee());
JSValue handlerValue = proxy->handler();
if (handlerValue.isNull())
@@ -541,6 +564,10 @@
bool ProxyObject::performDelete(ExecState* exec, PropertyName propertyName, DefaultDeleteFunction performDefaultDelete)
{
VM& vm = exec->vm();
+ if (UNLIKELY(!vm.isSafeToRecurse())) {
+ throwStackOverflowError(exec);
+ return false;
+ }
if (vm.propertyNames->isPrivateName(Identifier::fromUid(&vm, propertyName.uid())))
return performDefaultDelete();
@@ -613,6 +640,10 @@
bool ProxyObject::performPreventExtensions(ExecState* exec)
{
VM& vm = exec->vm();
+ if (UNLIKELY(!vm.isSafeToRecurse())) {
+ throwStackOverflowError(exec);
+ return false;
+ }
JSValue handlerValue = this->handler();
if (handlerValue.isNull()) {
@@ -661,6 +692,10 @@
bool ProxyObject::performIsExtensible(ExecState* exec)
{
VM& vm = exec->vm();
+ if (UNLIKELY(!vm.isSafeToRecurse())) {
+ throwStackOverflowError(exec);
+ return false;
+ }
JSValue handlerValue = this->handler();
if (handlerValue.isNull()) {
@@ -715,6 +750,10 @@
bool ProxyObject::performDefineOwnProperty(ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow)
{
VM& vm = exec->vm();
+ if (UNLIKELY(!vm.isSafeToRecurse())) {
+ throwStackOverflowError(exec);
+ return false;
+ }
JSObject* target = this->target();
auto performDefaultDefineOwnProperty = [&] {
@@ -808,6 +847,10 @@
void ProxyObject::performGetOwnPropertyNames(ExecState* exec, PropertyNameArray& trapResult, EnumerationMode enumerationMode)
{
VM& vm = exec->vm();
+ if (UNLIKELY(!vm.isSafeToRecurse())) {
+ throwStackOverflowError(exec);
+ return;
+ }
JSValue handlerValue = this->handler();
if (handlerValue.isNull()) {
throwVMTypeError(exec, ASCIILiteral(s_proxyAlreadyRevokedErrorMessage));
@@ -947,6 +990,11 @@
thisObject->performGetOwnPropertyNames(exec, propertyNameArray, enumerationMode);
}
+void ProxyObject::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNameArray, EnumerationMode enumerationMode)
+{
+ JSObject::getPropertyNames(object, exec, propertyNameArray, enumerationMode);
+}
+
void ProxyObject::getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode)
{
RELEASE_ASSERT_NOT_REACHED();
@@ -968,6 +1016,10 @@
ASSERT(prototype.isObject() || prototype.isNull());
VM& vm = exec->vm();
+ if (UNLIKELY(!vm.isSafeToRecurse())) {
+ throwStackOverflowError(exec);
+ return false;
+ }
JSValue handlerValue = this->handler();
if (handlerValue.isNull()) {
@@ -1028,6 +1080,10 @@
JSValue ProxyObject::performGetPrototype(ExecState* exec)
{
VM& vm = exec->vm();
+ if (UNLIKELY(!vm.isSafeToRecurse())) {
+ throwStackOverflowError(exec);
+ return JSValue();
+ }
JSValue handlerValue = this->handler();
if (handlerValue.isNull()) {
Modified: trunk/Source/_javascript_Core/runtime/ProxyObject.h (201494 => 201495)
--- trunk/Source/_javascript_Core/runtime/ProxyObject.h 2016-05-29 04:47:41 UTC (rev 201494)
+++ trunk/Source/_javascript_Core/runtime/ProxyObject.h 2016-05-29 19:01:36 UTC (rev 201495)
@@ -36,8 +36,6 @@
public:
typedef JSNonFinalObject Base;
- // We lie an say we override getPropertyNames() because it prevents
- // property name enumeration caching.
const static unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | TypeOfShouldCallGetCallData | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames | ProhibitsPropertyCaching;
static ProxyObject* create(ExecState* exec, JSGlobalObject* globalObject, JSValue target, JSValue handler)
@@ -87,6 +85,7 @@
static bool isExtensible(JSObject*, ExecState*);
static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+ static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
static NO_RETURN_DUE_TO_CRASH void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
static NO_RETURN_DUE_TO_CRASH void getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
static NO_RETURN_DUE_TO_CRASH void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
Added: trunk/Source/_javascript_Core/tests/stress/proxy-stack-overflow-exceptions.js (0 => 201495)
--- trunk/Source/_javascript_Core/tests/stress/proxy-stack-overflow-exceptions.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/proxy-stack-overflow-exceptions.js 2016-05-29 19:01:36 UTC (rev 201495)
@@ -0,0 +1,161 @@
+function shouldThrowStackOverflow(f) {
+ let threw = false;
+ const verbose = false;
+ try {
+ f();
+ } catch(e) {
+ threw = e instanceof RangeError;
+ }
+ if (!threw)
+ throw new Error("No stack overflow error thrown.");
+ if (verbose)
+ print("passed test: " + f + "\n\n");
+}
+
+const emptyFunction = function() { };
+let seenStartObjects = new Map;
+function makeLongProxyChain(startObject = emptyFunction) {
+ if (seenStartObjects.has(startObject))
+ return seenStartObjects.get(startObject);
+
+ let p = new Proxy(startObject, { });
+ for (let i = 0; i < 500000; i++)
+ p = new Proxy(p, {});
+ seenStartObjects.set(startObject, p);
+ return p;
+}
+
+shouldThrowStackOverflow(function longProxyChain() {
+ let f = makeLongProxyChain();
+ f.name;
+});
+
+shouldThrowStackOverflow(function effecivelyCyclicProxyProtoChain1() {
+ let t = {};
+ let p = new Proxy(t, {});
+ Object.setPrototypeOf(t, p);
+ t.propertyDoesNotExist;
+});
+
+shouldThrowStackOverflow(function effecivelyCyclicProxyProtoChain2() {
+ let t = {};
+ let p = new Proxy(t, {});
+ Object.setPrototypeOf(t, p);
+ for (var k in p)
+ break;
+});
+
+shouldThrowStackOverflow(function effecivelyCyclicProxyProtoChain3() {
+ let t = {};
+ let p = new Proxy(t, {});
+ Object.setPrototypeOf(t, p);
+ Object.prototype.toString.call(p);
+});
+
+shouldThrowStackOverflow(function longProxyChainBind() {
+ let p = makeLongProxyChain();
+ Function.prototype.bind.call(p)
+});
+
+shouldThrowStackOverflow(function longProxyChainPropertyAccess() {
+ let p = makeLongProxyChain();
+ p.nonExistentProperty;
+});
+
+shouldThrowStackOverflow(function longProxyChainReflectConstruct() {
+ let p = makeLongProxyChain();
+ Reflect.construct(Array, [], p);
+});
+
+shouldThrowStackOverflow(function longProxyChainReflectSet() {
+ let p = makeLongProxyChain();
+ Reflect.set([null], 0, 0, p);
+});
+
+shouldThrowStackOverflow(function longProxyChainReflectOwnKeys() {
+ let p = makeLongProxyChain();
+ Reflect.ownKeys(p);
+});
+
+shouldThrowStackOverflow(function longProxyChainGetPrototypeOf() {
+ let p = makeLongProxyChain();
+ Reflect.getPrototypeOf(p);
+});
+
+shouldThrowStackOverflow(function longProxyChainSetPrototypeOf() {
+ let p = makeLongProxyChain();
+ Reflect.setPrototypeOf(p, null);
+});
+
+shouldThrowStackOverflow(function longProxyChainGetOwnPropertyDescriptor() {
+ let p = makeLongProxyChain();
+ Reflect.getOwnPropertyDescriptor(p, "");
+});
+
+shouldThrowStackOverflow(function longProxyChainDefineProperty() {
+ let p = makeLongProxyChain();
+ Reflect.defineProperty(p, "", {});
+});
+
+shouldThrowStackOverflow(function longProxyChainIsExtensible() {
+ let p = makeLongProxyChain();
+ Reflect.isExtensible(p);
+});
+
+shouldThrowStackOverflow(function longProxyChainPreventExtensions() {
+ let p = makeLongProxyChain();
+ Reflect.preventExtensions(p)
+});
+
+shouldThrowStackOverflow(function longProxyChainDeleteProperty() {
+ let p = makeLongProxyChain();
+ Reflect.deleteProperty(p, "");
+});
+
+shouldThrowStackOverflow(function longProxyChainWithScope() {
+ let p = makeLongProxyChain();
+ with (p) {
+ propertyLookup;
+ }
+});
+
+shouldThrowStackOverflow(function longProxyChainWithScope2() {
+ let p = makeLongProxyChain();
+ with (p) {
+ storeToProperty = 0;
+ }
+});
+
+shouldThrowStackOverflow(function longProxyChainWithScope3() {
+ let p = makeLongProxyChain();
+ with (p) {
+ someFunctionPropertyLookup()
+ }
+});
+
+shouldThrowStackOverflow(function longProxyChainArrayPrototypePush() {
+ let p = makeLongProxyChain();
+ Array.prototype.push.call(p, 0);
+});
+
+shouldThrowStackOverflow(function longProxyChainWithScope4() {
+ let p = makeLongProxyChain();
+ with (p) {
+ eval("");
+ }
+});
+
+shouldThrowStackOverflow(function longProxyChainCall() {
+ let p = makeLongProxyChain();
+ p();
+});
+
+shouldThrowStackOverflow(function longProxyChainConstruct() {
+ let p = makeLongProxyChain();
+ new p;
+});
+
+shouldThrowStackOverflow(function longProxyChainHas() {
+ let p = makeLongProxyChain();
+ Reflect.has(p, "foo");
+});