Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (196965 => 196966)
--- trunk/Source/_javascript_Core/ChangeLog 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-02-23 00:51:02 UTC (rev 196966)
@@ -1,3 +1,57 @@
+2016-02-22 Saam barati <sbar...@apple.com>
+
+ InternalFunction::createSubclassStructure doesn't take into account that get() might throw
+ https://bugs.webkit.org/show_bug.cgi?id=154548
+
+ Reviewed by Mark Lam and Geoffrey Garen and Andreas Kling.
+
+ InternalFunction::createSubclassStructure calls newTarget.get(...) which can throw
+ an exception. Neither the function nor the call sites of the function took this into
+ account. This patch audits the call sites of the function to make it work in
+ the event that an exception is thrown.
+
+ * runtime/BooleanConstructor.cpp:
+ (JSC::constructWithBooleanConstructor):
+ * runtime/DateConstructor.cpp:
+ (JSC::constructDate):
+ * runtime/ErrorConstructor.cpp:
+ (JSC::Interpreter::constructWithErrorConstructor):
+ * runtime/FunctionConstructor.cpp:
+ (JSC::constructFunctionSkippingEvalEnabledCheck):
+ * runtime/InternalFunction.cpp:
+ (JSC::InternalFunction::createSubclassStructure):
+ * runtime/JSArrayBufferConstructor.cpp:
+ (JSC::constructArrayBuffer):
+ * runtime/JSGenericTypedArrayViewConstructorInlines.h:
+ (JSC::constructGenericTypedArrayView):
+ * runtime/JSGlobalObject.h:
+ (JSC::constructEmptyArray):
+ (JSC::constructArray):
+ (JSC::constructArrayNegativeIndexed):
+ * runtime/JSPromiseConstructor.cpp:
+ (JSC::constructPromise):
+ * runtime/MapConstructor.cpp:
+ (JSC::constructMap):
+ * runtime/NativeErrorConstructor.cpp:
+ (JSC::Interpreter::constructWithNativeErrorConstructor):
+ * runtime/NumberConstructor.cpp:
+ (JSC::constructWithNumberConstructor):
+ * runtime/RegExpConstructor.cpp:
+ (JSC::getRegExpStructure):
+ (JSC::constructRegExp):
+ (JSC::constructWithRegExpConstructor):
+ * runtime/SetConstructor.cpp:
+ (JSC::constructSet):
+ * runtime/StringConstructor.cpp:
+ (JSC::constructWithStringConstructor):
+ (JSC::StringConstructor::getConstructData):
+ * runtime/WeakMapConstructor.cpp:
+ (JSC::constructWeakMap):
+ * runtime/WeakSetConstructor.cpp:
+ (JSC::constructWeakSet):
+ * tests/stress/create-subclass-structure-might-throw.js: Added.
+ (assert):
+
2016-02-22 Ting-Wei Lan <lant...@gmail.com>
Fix build and implement functions to retrieve registers on FreeBSD
Modified: trunk/Source/_javascript_Core/runtime/BooleanConstructor.cpp (196965 => 196966)
--- trunk/Source/_javascript_Core/runtime/BooleanConstructor.cpp 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/runtime/BooleanConstructor.cpp 2016-02-23 00:51:02 UTC (rev 196966)
@@ -50,6 +50,8 @@
{
JSValue boolean = jsBoolean(exec->argument(0).toBoolean(exec));
Structure* booleanStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), asInternalFunction(exec->callee())->globalObject()->booleanObjectStructure());
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
BooleanObject* obj = BooleanObject::create(exec->vm(), booleanStructure);
obj->setInternalValue(exec->vm(), boolean);
return JSValue::encode(obj);
Modified: trunk/Source/_javascript_Core/runtime/DateConstructor.cpp (196965 => 196966)
--- trunk/Source/_javascript_Core/runtime/DateConstructor.cpp 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/runtime/DateConstructor.cpp 2016-02-23 00:51:02 UTC (rev 196966)
@@ -172,6 +172,8 @@
value = millisecondsFromComponents(exec, args, WTF::LocalTime);
Structure* dateStructure = InternalFunction::createSubclassStructure(exec, newTarget, globalObject->dateStructure());
+ if (exec->hadException())
+ return nullptr;
return DateInstance::create(vm, dateStructure, value);
}
Modified: trunk/Source/_javascript_Core/runtime/ErrorConstructor.cpp (196965 => 196966)
--- trunk/Source/_javascript_Core/runtime/ErrorConstructor.cpp 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/runtime/ErrorConstructor.cpp 2016-02-23 00:51:02 UTC (rev 196966)
@@ -52,6 +52,8 @@
{
JSValue message = exec->argumentCount() ? exec->argument(0) : jsUndefined();
Structure* errorStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), asInternalFunction(exec->callee())->globalObject()->errorStructure());
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
return JSValue::encode(ErrorInstance::create(exec, errorStructure, message, nullptr, TypeNothing, false));
}
Modified: trunk/Source/_javascript_Core/runtime/FunctionConstructor.cpp (196965 => 196966)
--- trunk/Source/_javascript_Core/runtime/FunctionConstructor.cpp 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/runtime/FunctionConstructor.cpp 2016-02-23 00:51:02 UTC (rev 196966)
@@ -124,8 +124,11 @@
return exec->vm().throwException(exec, exception);
}
+ Structure* subclassStructure = InternalFunction::createSubclassStructure(exec, newTarget, globalObject->functionStructure());
+ if (exec->hadException())
+ return nullptr;
- return JSFunction::create(exec->vm(), function, globalObject, InternalFunction::createSubclassStructure(exec, newTarget, globalObject->functionStructure()));
+ return JSFunction::create(exec->vm(), function, globalObject, subclassStructure);
}
// ECMA 15.3.2 The Function Constructor
Modified: trunk/Source/_javascript_Core/runtime/InternalFunction.cpp (196965 => 196966)
--- trunk/Source/_javascript_Core/runtime/InternalFunction.cpp 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/runtime/InternalFunction.cpp 2016-02-23 00:51:02 UTC (rev 196966)
@@ -97,10 +97,13 @@
// Note, Reflect.construct might cause the profile to churn but we don't care.
JSObject* prototype = jsDynamicCast<JSObject*>(newTarget.get(exec, exec->propertyNames().prototype));
+ ASSERT(!exec->hadException());
if (prototype)
return targetFunction->rareData(vm)->createInternalFunctionAllocationStructureFromBase(vm, prototype, baseClass);
} else {
JSObject* prototype = jsDynamicCast<JSObject*>(newTarget.get(exec, exec->propertyNames().prototype));
+ if (exec->hadException())
+ return nullptr;
if (prototype) {
// 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.
Modified: trunk/Source/_javascript_Core/runtime/JSArrayBufferConstructor.cpp (196965 => 196966)
--- trunk/Source/_javascript_Core/runtime/JSArrayBufferConstructor.cpp 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/runtime/JSArrayBufferConstructor.cpp 2016-02-23 00:51:02 UTC (rev 196966)
@@ -97,6 +97,8 @@
return throwVMError(exec, createOutOfMemoryError(exec));
Structure* arrayBufferStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), constructor->globalObject()->arrayBufferStructure());
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
JSArrayBuffer* result = JSArrayBuffer::create(exec->vm(), arrayBufferStructure, buffer.release());
return JSValue::encode(result);
Modified: trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewConstructorInlines.h (196965 => 196966)
--- trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewConstructorInlines.h 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewConstructorInlines.h 2016-02-23 00:51:02 UTC (rev 196966)
@@ -219,6 +219,8 @@
static EncodedJSValue JSC_HOST_CALL constructGenericTypedArrayView(ExecState* exec)
{
Structure* structure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), asInternalFunction(exec->callee())->globalObject()->typedArrayStructure(ViewClass::TypedArrayStorageType));
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
size_t argCount = exec->argumentCount();
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (196965 => 196966)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2016-02-23 00:51:02 UTC (rev 196966)
@@ -731,6 +731,8 @@
structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(exec, ArrayWithArrayStorage, newTarget);
else
structure = globalObject->arrayStructureForProfileDuringAllocation(exec, profile, newTarget);
+ if (exec->hadException())
+ return nullptr;
return ArrayAllocationProfile::updateLastAllocationFor(profile, JSArray::create(exec->vm(), structure, initialLength));
}
@@ -742,7 +744,10 @@
inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, const ArgList& values, JSValue newTarget = JSValue())
{
- return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArray(exec, globalObject->arrayStructureForProfileDuringAllocation(exec, profile, newTarget), values));
+ Structure* structure = globalObject->arrayStructureForProfileDuringAllocation(exec, profile, newTarget);
+ if (exec->hadException())
+ return nullptr;
+ return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArray(exec, structure, values));
}
inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, const ArgList& values, JSValue newTarget = JSValue())
@@ -752,7 +757,10 @@
inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, const JSValue* values, unsigned length, JSValue newTarget = JSValue())
{
- return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArray(exec, globalObject->arrayStructureForProfileDuringAllocation(exec, profile, newTarget), values, length));
+ Structure* structure = globalObject->arrayStructureForProfileDuringAllocation(exec, profile, newTarget);
+ if (exec->hadException())
+ return nullptr;
+ return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArray(exec, structure, values, length));
}
inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, unsigned length, JSValue newTarget = JSValue())
@@ -762,7 +770,10 @@
inline JSArray* constructArrayNegativeIndexed(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, const JSValue* values, unsigned length, JSValue newTarget = JSValue())
{
- return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArrayNegativeIndexed(exec, globalObject->arrayStructureForProfileDuringAllocation(exec, profile, newTarget), values, length));
+ Structure* structure = globalObject->arrayStructureForProfileDuringAllocation(exec, profile, newTarget);
+ if (exec->hadException())
+ return nullptr;
+ return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArrayNegativeIndexed(exec, structure, values, length));
}
inline JSArray* constructArrayNegativeIndexed(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, unsigned length, JSValue newTarget = JSValue())
Modified: trunk/Source/_javascript_Core/runtime/JSPromiseConstructor.cpp (196965 => 196966)
--- trunk/Source/_javascript_Core/runtime/JSPromiseConstructor.cpp 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/runtime/JSPromiseConstructor.cpp 2016-02-23 00:51:02 UTC (rev 196966)
@@ -104,6 +104,8 @@
return throwVMTypeError(exec);
Structure* promiseStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), globalObject->promiseStructure());
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
JSPromise* promise = JSPromise::create(vm, promiseStructure);
promise->initialize(exec, globalObject, exec->argument(0));
Modified: trunk/Source/_javascript_Core/runtime/MapConstructor.cpp (196965 => 196966)
--- trunk/Source/_javascript_Core/runtime/MapConstructor.cpp 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/runtime/MapConstructor.cpp 2016-02-23 00:51:02 UTC (rev 196966)
@@ -57,6 +57,8 @@
{
JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
Structure* mapStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), globalObject->mapStructure());
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
JSMap* map = JSMap::create(exec, mapStructure);
JSValue iterable = exec->argument(0);
if (iterable.isUndefinedOrNull())
Modified: trunk/Source/_javascript_Core/runtime/NativeErrorConstructor.cpp (196965 => 196966)
--- trunk/Source/_javascript_Core/runtime/NativeErrorConstructor.cpp 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/runtime/NativeErrorConstructor.cpp 2016-02-23 00:51:02 UTC (rev 196966)
@@ -64,6 +64,8 @@
{
JSValue message = exec->argument(0);
Structure* errorStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), jsCast<NativeErrorConstructor*>(exec->callee())->errorStructure());
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
ASSERT(errorStructure);
return JSValue::encode(ErrorInstance::create(exec, errorStructure, message, nullptr, TypeNothing, false));
}
Modified: trunk/Source/_javascript_Core/runtime/NumberConstructor.cpp (196965 => 196966)
--- trunk/Source/_javascript_Core/runtime/NumberConstructor.cpp 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/runtime/NumberConstructor.cpp 2016-02-23 00:51:02 UTC (rev 196966)
@@ -81,8 +81,11 @@
static EncodedJSValue JSC_HOST_CALL constructWithNumberConstructor(ExecState* exec)
{
double n = exec->argumentCount() ? exec->uncheckedArgument(0).toNumber(exec) : 0;
- NumberObject* object = NumberObject::create(exec->vm(), InternalFunction::createSubclassStructure(exec, exec->newTarget(), asInternalFunction(exec->callee())->globalObject()->numberObjectStructure()));
+ Structure* structure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), exec->lexicalGlobalObject()->numberObjectStructure());
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
+ NumberObject* object = NumberObject::create(exec->vm(), structure);
object->setInternalValue(exec->vm(), jsNumber(n));
return JSValue::encode(object);
}
Modified: trunk/Source/_javascript_Core/runtime/RegExpConstructor.cpp (196965 => 196966)
--- trunk/Source/_javascript_Core/runtime/RegExpConstructor.cpp 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/runtime/RegExpConstructor.cpp 2016-02-23 00:51:02 UTC (rev 196966)
@@ -249,9 +249,8 @@
inline Structure* getRegExpStructure(ExecState* exec, JSGlobalObject* globalObject, JSValue newTarget)
{
Structure* structure = globalObject->regExpStructure();
- if (newTarget != jsUndefined()) {
+ if (newTarget != jsUndefined())
structure = InternalFunction::createSubclassStructure(exec, newTarget, structure);
- }
return structure;
}
@@ -267,8 +266,11 @@
// If called as a function, this just returns the first argument (see 15.10.3.1).
if (newTarget != jsUndefined()) {
RegExp* regExp = static_cast<RegExpObject*>(asObject(arg0))->regExp();
+ Structure* structure = getRegExpStructure(exec, globalObject, newTarget);
+ if (exec->hadException())
+ return nullptr;
- return RegExpObject::create(exec->vm(), getRegExpStructure(exec, globalObject, newTarget), regExp);
+ return RegExpObject::create(exec->vm(), structure, regExp);
}
return asObject(arg0);
}
@@ -291,7 +293,10 @@
if (!regExp->isValid())
return vm.throwException(exec, createSyntaxError(exec, regExp->errorMessage()));
- return RegExpObject::create(vm, getRegExpStructure(exec, globalObject, newTarget), regExp);
+ Structure* structure = getRegExpStructure(exec, globalObject, newTarget);
+ if (exec->hadException())
+ return nullptr;
+ return RegExpObject::create(vm, structure, regExp);
}
static EncodedJSValue JSC_HOST_CALL constructWithRegExpConstructor(ExecState* exec)
Modified: trunk/Source/_javascript_Core/runtime/SetConstructor.cpp (196965 => 196966)
--- trunk/Source/_javascript_Core/runtime/SetConstructor.cpp 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/runtime/SetConstructor.cpp 2016-02-23 00:51:02 UTC (rev 196966)
@@ -58,6 +58,8 @@
{
JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
Structure* setStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), globalObject->setStructure());
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
JSSet* set = JSSet::create(exec, setStructure);
JSValue iterable = exec->argument(0);
if (iterable.isUndefinedOrNull())
Modified: trunk/Source/_javascript_Core/runtime/StringConstructor.cpp (196965 => 196966)
--- trunk/Source/_javascript_Core/runtime/StringConstructor.cpp 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/runtime/StringConstructor.cpp 2016-02-23 00:51:02 UTC (rev 196966)
@@ -125,10 +125,13 @@
JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
VM& vm = exec->vm();
+ Structure* structure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), globalObject->stringObjectStructure());
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
+
if (!exec->argumentCount())
- return JSValue::encode(StringObject::create(vm, InternalFunction::createSubclassStructure(exec, exec->newTarget(), globalObject->stringObjectStructure())));
-
- return JSValue::encode(StringObject::create(vm, InternalFunction::createSubclassStructure(exec, exec->newTarget(), globalObject->stringObjectStructure()), exec->uncheckedArgument(0).toString(exec)));
+ return JSValue::encode(StringObject::create(vm, structure));
+ return JSValue::encode(StringObject::create(vm, structure, exec->uncheckedArgument(0).toString(exec)));
}
ConstructType StringConstructor::getConstructData(JSCell*, ConstructData& constructData)
Modified: trunk/Source/_javascript_Core/runtime/WeakMapConstructor.cpp (196965 => 196966)
--- trunk/Source/_javascript_Core/runtime/WeakMapConstructor.cpp 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/runtime/WeakMapConstructor.cpp 2016-02-23 00:51:02 UTC (rev 196966)
@@ -55,6 +55,8 @@
{
JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
Structure* weakMapStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), globalObject->weakMapStructure());
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
JSWeakMap* weakMap = JSWeakMap::create(exec, weakMapStructure);
JSValue iterable = exec->argument(0);
if (iterable.isUndefinedOrNull())
Modified: trunk/Source/_javascript_Core/runtime/WeakSetConstructor.cpp (196965 => 196966)
--- trunk/Source/_javascript_Core/runtime/WeakSetConstructor.cpp 2016-02-23 00:48:48 UTC (rev 196965)
+++ trunk/Source/_javascript_Core/runtime/WeakSetConstructor.cpp 2016-02-23 00:51:02 UTC (rev 196966)
@@ -55,6 +55,8 @@
{
JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
Structure* weakSetStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), globalObject->weakSetStructure());
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
JSWeakSet* weakSet = JSWeakSet::create(exec, weakSetStructure);
JSValue iterable = exec->argument(0);
if (iterable.isUndefinedOrNull())
Added: trunk/Source/_javascript_Core/tests/stress/create-subclass-structure-might-throw.js (0 => 196966)
--- trunk/Source/_javascript_Core/tests/stress/create-subclass-structure-might-throw.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/create-subclass-structure-might-throw.js 2016-02-23 00:51:02 UTC (rev 196966)
@@ -0,0 +1,34 @@
+function assert(b) {
+ if (!b)
+ throw new Error("bad assertion.");
+}
+
+let targets = [Function, String, Array, Set, Map, WeakSet, WeakMap, RegExp, Number, Promise, Date, Boolean, Error, TypeError, SyntaxError, ArrayBuffer, Int32Array, Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Uint32Array, Float32Array, Float64Array, DataView];
+for (let target of targets) {
+ let error = null;
+ let called = false;
+ let handler = {
+ get: function(theTarget, propName) {
+ assert(propName === "prototype");
+ error = new Error;
+ called = true;
+ throw error;
+ }
+ };
+
+ let proxy = new Proxy(target, handler);
+
+ for (let i = 0; i < 500; i++) {
+ let threw = false;
+ try {
+ new proxy;
+ } catch(e) {
+ threw = true;
+ assert(e === error);
+ error = null;
+ }
+ assert(threw);
+ assert(called);
+ called = false;
+ }
+}