Firefox · SpiderMonkey
CVE-2026-2766
UAF in SpiderMonkey
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
switchjs/src/jit/CacheIRCompiler.cpp |
modified | |
ifjs/src/jit/CacheIRCompiler.cpp |
modified |
Files Changed
js/src/jit/BaselineIC.hjs/src/jit/CacheIR.cppjs/src/jit/CacheIR.hjs/src/jit/CacheIRCloner.hjs/src/jit/CacheIRCompiler.cppjs/src/jit/CacheIROps.yamljs/src/jit/CacheIRWriter.hjs/src/jit/GenerateCacheIRFiles.pyjs/src/jit/JitScript.cppjs/src/jit/WarpOracle.cppjs/src/jit/WarpSnapshot.cpp
Patch
diff --git a/js/src/jit/BaselineIC.h b/js/src/jit/BaselineIC.h
index 5b469b300ac..88de0e06ac7 100644
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -299,7 +299,9 @@ class ICCacheIRStub final : public ICStub {
void trace(JSTracer* trc);
bool traceWeak(JSTracer* trc);
- ICCacheIRStub* clone(JSRuntime* rt, ICStubSpace& newSpace);
+ enum class ICScriptHandling { MarkActive, AssertActive };
+ ICCacheIRStub* clone(JSRuntime* rt, ICStubSpace& newSpace,
+ ICScriptHandling icScriptHandling);
// Returns true if this stub can call JS or VM code that can trigger a GC.
bool makesGCCalls() const;
diff --git a/js/src/jit/CacheIR.cpp b/js/src/jit/CacheIR.cpp
index 3ae32cdc03c..1946de33476 100644
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -242,6 +242,9 @@ uint32_t CacheIRCloner::getRawInt32Field(uint32_t stubOffset) {
const void* CacheIRCloner::getRawPointerField(uint32_t stubOffset) {
return reinterpret_cast<const void*>(readStubWord(stubOffset));
}
+const ICScript* CacheIRCloner::getICScriptField(uint32_t stubOffset) {
+ return reinterpret_cast<const ICScript*>(readStubWord(stubOffset));
+}
uint64_t CacheIRCloner::getRawInt64Field(uint32_t stubOffset) {
return static_cast<uint64_t>(readStubInt64(stubOffset));
}
diff --git a/js/src/jit/CacheIR.h b/js/src/jit/CacheIR.h
index 544e3cb7605..893cc2c1801 100644
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -241,6 +241,7 @@ class StubField {
// These fields take up a single word.
RawInt32,
RawPointer,
+ ICScript,
Shape,
WeakShape,
JSObject,
@@ -314,6 +315,8 @@ inline const char* StubFieldTypeName(StubField::Type ty) {
return "RawInt32";
case StubField::Type::RawPointer:
return "RawPointer";
+ case StubField::Type::ICScript:
+ return "ICScript";
case StubField::Type::Shape:
return "Shape";
case StubField::Type::WeakShape:
diff --git a/js/src/jit/CacheIRCloner.h b/js/src/jit/CacheIRCloner.h
index 2ecf37cc2f4..6ccb58619fd 100644
--- a/js/src/jit/CacheIRCloner.h
+++ b/js/src/jit/CacheIRCloner.h
@@ -70,6 +70,7 @@ class MOZ_RAII CacheIRCloner {
JitCode* getJitCodeField(uint32_t stubOffset);
uint32_t getRawInt32Field(uint32_t stubOffset);
const void* getRawPointerField(uint32_t stubOffset);
+ const ICScript* getICScriptField(uint32_t stubOffset);
jsid getIdField(uint32_t stubOffset);
Value getValueField(uint32_t stubOffset);
Value getWeakValueField(uint32_t stubOffset);
diff --git a/js/src/jit/CacheIRCompiler.cpp b/js/src/jit/CacheIRCompiler.cpp
index 3a3825c4d9e..0a4edd05f62 100644
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -1127,6 +1127,7 @@ static void InitWordStubField(StubField::Type type, void* dest,
switch (type) {
case StubField::Type::RawInt32:
case StubField::Type::RawPointer:
+ case StubField::Type::ICScript:
case StubField::Type::AllocSite:
*static_cast<uintptr_t*>(dest) = value;
break;
@@ -1188,6 +1189,7 @@ static void InitInt64StubField(StubField::Type type, void* dest,
break;
case StubField::Type::RawInt32:
case StubField::Type::RawPointer:
+ case StubField::Type::ICScript:
case StubField::Type::AllocSite:
case StubField::Type::Shape:
case StubField::Type::WeakShape:
@@ -1217,7 +1219,8 @@ void CacheIRWriter::copyStubData(uint8_t* dest) const {
}
}
-ICCacheIRStub* ICCacheIRStub::clone(JSRuntime* rt, ICStubSpace& newSpace) {
+ICCacheIRStub* ICCacheIRStub::clone(JSRuntime* rt, ICStubSpace& newSpace,
+ ICScriptHandling icScriptHandling) {
const CacheIRStubInfo* info = stubInfo();
MOZ_ASSERT(info->makesGCCalls());
@@ -1250,6 +1253,15 @@ ICCacheIRStub* ICCacheIRStub::clone(JSRuntime* rt, ICStubSpace& newSpace) {
InitWordStubField(type, dest, *srcField);
src += sizeof(uintptr_t);
dest += sizeof(uintptr_t);
+ if (type == StubField::Type::ICScript) {
+ auto* icScript = reinterpret_cast<ICScript*>(*srcField);
+ if (icScriptHandling == ICScriptHandling::MarkActive) {
+ icScript->setActive();
+ } else {
+ MOZ_ASSERT(icScriptHandling == ICScriptHandling::AssertActive);
+ MOZ_RELEASE_ASSERT(icScript->active());
+ }
+ }
} else {
const uint64_t* srcField = reinterpret_cast<const uint64_t*>(src);
InitInt64StubField(type, dest, *srcField);
@@ -1286,6 +1298,7 @@ void jit::TraceCacheIRStub(JSTracer* trc, T* stub,
switch (fieldType) {
case Type::RawInt32:
case Type::RawPointer:
+ case Type::ICScript:
case Type::RawInt64:
case Type::Double:
break;
@@ -1431,6 +1444,7 @@ bool jit::TraceWeakCacheIRStub(JSTracer* trc, T* stub,
return !isDead;
case Type::RawInt32:
case Type::RawPointer:
+ case Type::ICScript:
case Type::Shape:
case Type::JSObject:
case Type::Symbol:
diff --git a/js/src/jit/CacheIROps.yaml b/js/src/jit/CacheIROps.yaml
index 2c9ace66157..310b08360a7 100644
--- a/js/src/jit/CacheIROps.yaml
+++ b/js/src/jit/CacheIROps.yaml
@@ -2064,7 +2064,7 @@
receiver: ObjId
callee: ObjId
rhs: ValId
- icScript: RawPointerField
+ icScript: ICScriptField
sameRealm: BoolImm
nargsAndFlags: RawInt32Field
@@ -2257,7 +2257,7 @@
args:
callee: ObjId
argc: Int32Id
- icScript: RawPointerField
+ icScript: ICScriptField
flags: CallFlagsImm
argcFixed: UInt32Imm
@@ -2704,7 +2704,7 @@
args:
receiver: ValId
callee: ObjId
- icScript: RawPointerField
+ icScript: ICScriptField
sameRealm: BoolImm
nargsAndFlags: RawInt32Field
diff --git a/js/src/jit/CacheIRWriter.h b/js/src/jit/CacheIRWriter.h
index d0b9cc4c064..9d52f04dab8 100644
--- a/js/src/jit/CacheIRWriter.h
+++ b/js/src/jit/CacheIRWriter.h
@@ -237,6 +237,9 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter {
void writeRawPointerField(const void* ptr) {
addStubField(uintptr_t(ptr), StubField::Type::RawPointer);
}
+ void writeICScriptField(const ICScript* icScript) {
+ addStubField(uintptr_t(icScript), StubField::Type::ICScript);
+ }
void writeIdField(jsid id) {
addStubField(id.asRawBits(), StubField::Type::Id);
}
diff --git a/js/src/jit/GenerateCacheIRFiles.py b/js/src/jit/GenerateCacheIRFiles.py
index 40c3b504530..6ed6a20aae5 100644
--- a/js/src/jit/GenerateCacheIRFiles.py
+++ b/js/src/jit/GenerateCacheIRFiles.py
@@ -75,6 +75,7 @@ arg_writer_info = {
"JitCodeField": ("JitCode*", "writeJitCodeField"),
"RawInt32Field": ("uint32_t", "writeRawInt32Field"),
"RawPointerField": ("const void*", "writeRawPointerField"),
+ "ICScriptField": ("const ICScript*", "writeICScriptField"),
"IdField": ("jsid", "writeIdField"),
"ValueField": ("const Value&", "writeValueField"),
"WeakValueField": ("const Value&", "writeWeakValueField"),
@@ -181,6 +182,7 @@ arg_reader_info = {
"JitCodeField": ("uint32_t", "Offset", "reader.stubOffset()"),
"RawInt32Field": ("uint32_t", "Offset", "reader.stubOffset()"),
"RawPointerField": ("uint32_t", "Offset", "reader.stubOffset()"),
+ "ICScriptField": ("uint32_t", "Offset", "reader.stubOffset()"),
"IdField": ("uint32_t", "Offset", "reader.stubOffset()"),
"ValueField": ("uint32_t", "Offset", "reader.stubOffset()"),
"WeakValueField": ("uint32_t", "Offset", "reader.stubOffset()"),
@@ -326,6 +328,7 @@ arg_spewer_method = {
"JitCodeField": "spewField",
"RawInt32Field": "spewField",
"RawPointerField": "spewField",
+ "ICScriptField": "spewField",
"IdField": "spewField",
"ValueField": "spewField",
"WeakValueField": "spewField",
@@ -469,6 +472,7 @@ arg_length = {
"JitCodeField": 1,
"RawInt32Field": 1,
Loading diff…
References
On This Page