Firefox · SpiderMonkey
CVE-2025-4918
OOB in SpiderMonkey
Overview
Critical
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifjs/src/builtin/Promise.cpp |
modified |
Files Changed
js/src/builtin/Promise.cpp
Patch
diff --git a/js/src/builtin/Promise.cpp b/js/src/builtin/Promise.cpp
index 34f9c28961a..60d09e03a13 100644
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -99,7 +99,7 @@ enum RejectFunctionSlots {
enum PromiseCombinatorElementFunctionSlots {
PromiseCombinatorElementFunctionSlot_Data = 0,
- PromiseCombinatorElementFunctionSlot_ElementIndex,
+ PromiseCombinatorElementFunctionSlot_ElementIndexOrResolveFunc,
};
enum ReactionJobSlots {
@@ -3241,7 +3241,8 @@ static bool Promise_static_all(JSContext* cx, unsigned argc, Value* vp) {
static JSFunction* NewPromiseCombinatorElementFunction(
JSContext* cx, Native native,
- Handle<PromiseCombinatorDataHolder*> dataHolder, uint32_t index);
+ Handle<PromiseCombinatorDataHolder*> dataHolder, uint32_t index,
+ Handle<Value> maybeResolveFunc);
static bool PromiseAllResolveElementFunction(JSContext* cx, unsigned argc,
Value* vp);
@@ -3343,7 +3344,8 @@ static bool PromiseAllResolveElementFunction(JSContext* cx, unsigned argc,
// Steps 4.j-q.
JSFunction* resolveFunc = NewPromiseCombinatorElementFunction(
- cx, PromiseAllResolveElementFunction, dataHolder, index);
+ cx, PromiseAllResolveElementFunction, dataHolder, index,
+ UndefinedHandleValue);
if (!resolveFunc) {
return nullptr;
}
@@ -3990,7 +3992,8 @@ template <typename T>
static JSFunction* NewPromiseCombinatorElementFunction(
JSContext* cx, Native native,
- Handle<PromiseCombinatorDataHolder*> dataHolder, uint32_t index) {
+ Handle<PromiseCombinatorDataHolder*> dataHolder, uint32_t index,
+ Handle<Value> maybeResolveFunc) {
JSFunction* fn = NewNativeFunction(
cx, native, 1, nullptr, gc::AllocKind::FUNCTION_EXTENDED, GenericObject);
if (!fn) {
@@ -3999,8 +4002,15 @@ static JSFunction* NewPromiseCombinatorElementFunction(
fn->setExtendedSlot(PromiseCombinatorElementFunctionSlot_Data,
ObjectValue(*dataHolder));
- fn->setExtendedSlot(PromiseCombinatorElementFunctionSlot_ElementIndex,
- Int32Value(index));
+ if (maybeResolveFunc.isObject()) {
+ fn->setExtendedSlot(
+ PromiseCombinatorElementFunctionSlot_ElementIndexOrResolveFunc,
+ maybeResolveFunc);
+ } else {
+ fn->setExtendedSlot(
+ PromiseCombinatorElementFunctionSlot_ElementIndexOrResolveFunc,
+ Int32Value(index));
+ }
return fn;
}
@@ -4033,6 +4043,14 @@ static bool PromiseCombinatorElementFunctionAlreadyCalled(
// Step 1. Let F be the active function object.
JSFunction* fn = &args.callee().as<JSFunction>();
+ constexpr size_t indexOrResolveFuncSlot =
+ PromiseCombinatorElementFunctionSlot_ElementIndexOrResolveFunc;
+ if (fn->getExtendedSlot(indexOrResolveFuncSlot).isObject()) {
+ Value slotVal = fn->getExtendedSlot(indexOrResolveFuncSlot);
+ fn = &slotVal.toObject().as<JSFunction>();
+ }
+ MOZ_RELEASE_ASSERT(fn->getExtendedSlot(indexOrResolveFuncSlot).isInt32());
+
// Promise.all functions
// Step 2. If F.[[AlreadyCalled]] is true, return undefined.
// Promise.allSettled functions
@@ -4061,9 +4079,7 @@ static bool PromiseCombinatorElementFunctionAlreadyCalled(
// Step 4. Let index be F.[[Index]].
// Promise.allSettled functions
// Step 5. Let index be F.[[Index]].
- int32_t idx =
- fn->getExtendedSlot(PromiseCombinatorElementFunctionSlot_ElementIndex)
- .toInt32();
+ int32_t idx = fn->getExtendedSlot(indexOrResolveFuncSlot).toInt32();
MOZ_ASSERT(idx >= 0);
*index = uint32_t(idx);
@@ -4117,7 +4133,8 @@ static bool PromiseCombinatorElementFunctionAlreadyCalled(
// Steps 4.j-q.
JSFunction* resolveFunc = NewPromiseCombinatorElementFunction(
- cx, PromiseAllResolveElementFunction, dataHolder, index);
+ cx, PromiseAllResolveElementFunction, dataHolder, index,
+ UndefinedHandleValue);
if (!resolveFunc) {
return false;
}
@@ -4341,7 +4358,8 @@ static bool Promise_static_allSettled(JSContext* cx, unsigned argc, Value* vp) {
// Steps 4.j-r.
JSFunction* resolveFunc = NewPromiseCombinatorElementFunction(
- cx, PromiseAllSettledResolveElementFunction, dataHolder, index);
+ cx, PromiseAllSettledResolveElementFunction, dataHolder, index,
+ UndefinedHandleValue);
if (!resolveFunc) {
return false;
}
@@ -4349,7 +4367,8 @@ static bool Promise_static_allSettled(JSContext* cx, unsigned argc, Value* vp) {
// Steps 4.s-z.
JSFunction* rejectFunc = NewPromiseCombinatorElementFunction(
- cx, PromiseAllSettledRejectElementFunction, dataHolder, index);
+ cx, PromiseAllSettledRejectElementFunction, dataHolder, index,
+ resolveFunVal);
if (!rejectFunc) {
return false;
}
@@ -4578,7 +4597,8 @@ static void ThrowAggregateError(JSContext* cx,
// Steps 4.j-q.
JSFunction* rejectFunc = NewPromiseCombinatorElementFunction(
- cx, PromiseAnyRejectElementFunction, dataHolder, index);
+ cx, PromiseAnyRejectElementFunction, dataHolder, index,
+ UndefinedHandleValue);
if (!rejectFunc) {
return false;
}
Loading diff…
References
On This Page