Firefox · SpiderMonkey
CVE-2026-117898
Logic Error in SpiderMonkey
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
CACHEOP_CASEjs/src/vm/PortableBaselineInterpret.cpp |
modified | |
ifjs/src/vm/PortableBaselineInterpret.cpp |
modified | |
withjs/src/jit-test/tests/cacheir/bug2079040.js |
modified | |
forjs/src/jit-test/tests/cacheir/bug2079040.js |
modified | |
ifjs/src/jit-test/tests/cacheir/bug2079040.js |
modified |
Files Changed
js/src/jit-test/tests/cacheir/bug2079040.jsjs/src/jit/CacheIRCompiler.cppjs/src/jit/CacheIROps.yamljs/src/jit/CacheIRWriter.hjs/src/jit/WarpCacheIRTranspiler.cppjs/src/vm/PortableBaselineInterpret.cpp
Patch
diff --git a/js/src/jit/CacheIRCompiler.cpp b/js/src/jit/CacheIRCompiler.cpp
index f3a8fb85d37..1cf65a9bc43 100644
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -3068,21 +3068,25 @@ bool CacheIRCompiler::emitDoubleParseIntResult(NumberOperandId numId) {
return true;
}
-bool CacheIRCompiler::emitStringToAtom(StringOperandId stringId) {
+bool CacheIRCompiler::emitStringToAtom(StringOperandId stringId,
+ StringOperandId resultId) {
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
Register str = allocator.useRegister(masm, stringId);
- AutoScratchRegister scratch(allocator, masm);
+ Register output = allocator.defineRegister(masm, resultId);
FailurePath* failure;
if (!addFailurePath(&failure)) {
return false;
}
- Label done, vmCall;
- masm.branchTest32(Assembler::NonZero, Address(str, JSString::offsetOfFlags()),
- Imm32(StringFlags::ATOM_BIT), &done);
+ Label done, notAtom, vmCall;
+ masm.branchTest32(Assembler::Zero, Address(str, JSString::offsetOfFlags()),
+ Imm32(StringFlags::ATOM_BIT), ¬Atom);
+ masm.movePtr(str, output);
+ masm.jump(&done);
- masm.tryFastAtomize(str, scratch, str, &vmCall);
+ masm.bind(¬Atom);
+ masm.tryFastAtomize(str, output, output, &vmCall);
masm.jump(&done);
masm.bind(&vmCall);
@@ -3090,19 +3094,18 @@ bool CacheIRCompiler::emitStringToAtom(StringOperandId stringId) {
masm.PushRegsInMask(save);
using Fn = JSAtom* (*)(JSContext * cx, JSString * str);
- masm.setupUnalignedABICall(scratch);
- masm.loadJSContext(scratch);
- masm.passABIArg(scratch);
+ masm.setupUnalignedABICall(output);
+ masm.loadJSContext(output);
+ masm.passABIArg(output);
masm.passABIArg(str);
masm.callWithABI<Fn, jit::AtomizeStringNoGC>();
- masm.storeCallPointerResult(scratch);
+ masm.storeCallPointerResult(output);
LiveRegisterSet ignore;
- ignore.add(scratch);
+ ignore.add(output);
masm.PopRegsInMaskIgnore(save, ignore);
- masm.branchPtr(Assembler::Equal, scratch, Imm32(0), failure->label());
- masm.movePtr(scratch.get(), str);
+ masm.branchTestPtr(Assembler::Zero, output, output, failure->label());
masm.bind(&done);
return true;
diff --git a/js/src/jit/CacheIROps.yaml b/js/src/jit/CacheIROps.yaml
index e7356f34685..196137a3984 100644
--- a/js/src/jit/CacheIROps.yaml
+++ b/js/src/jit/CacheIROps.yaml
@@ -640,10 +640,10 @@
- name: StringToAtom
shared: true
transpile: true
- custom_writer: true
cost_estimate: 4
args:
str: StringId
+ result: StringId
- name: BooleanToNumber
shared: true
diff --git a/js/src/jit/CacheIRWriter.h b/js/src/jit/CacheIRWriter.h
index 3b13dc8b94e..86d3566780c 100644
--- a/js/src/jit/CacheIRWriter.h
+++ b/js/src/jit/CacheIRWriter.h
@@ -479,11 +479,6 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter {
return NumberOperandId(input.id());
}
- StringOperandId stringToAtom(StringOperandId input) {
- stringToAtom_(input);
- return input;
- }
-
ValOperandId boxObject(ObjOperandId input) {
return ValOperandId(input.id());
}
diff --git a/js/src/jit/WarpCacheIRTranspiler.cpp b/js/src/jit/WarpCacheIRTranspiler.cpp
index 2442edcb4ce..476ee74872e 100644
--- a/js/src/jit/WarpCacheIRTranspiler.cpp
+++ b/js/src/jit/WarpCacheIRTranspiler.cpp
@@ -1683,14 +1683,14 @@ bool WarpCacheIRTranspiler::emitBooleanToNumber(BooleanOperandId inputId,
return defineOperand(resultId, ins);
}
-bool WarpCacheIRTranspiler::emitStringToAtom(StringOperandId strId) {
+bool WarpCacheIRTranspiler::emitStringToAtom(StringOperandId strId,
+ StringOperandId resultId) {
MDefinition* str = getOperand(strId);
auto* ins = MToHashableString::New(alloc(), str);
add(ins);
- setOperand(strId, ins);
- return true;
+ return defineOperand(resultId, ins);
}
bool WarpCacheIRTranspiler::emitLoadInt32Result(Int32OperandId valId) {
diff --git a/js/src/vm/PortableBaselineInterpret.cpp b/js/src/vm/PortableBaselineInterpret.cpp
index f4396e1266e..0bdda223452 100644
--- a/js/src/vm/PortableBaselineInterpret.cpp
+++ b/js/src/vm/PortableBaselineInterpret.cpp
@@ -4758,13 +4758,15 @@ uint64_t ICInterpretOps(uint64_t arg0, uint64_t arg1, ICStub* stub,
CACHEOP_CASE(StringToAtom) {
StringOperandId strId = cacheIRReader.stringOperandId();
+ StringOperandId resultId = cacheIRReader.stringOperandId();
+ BOUNDSCHECK(resultId);
JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
JSAtom* result =
AtomizeStringNoGC(ctx.frameMgr.cxForLocalUseOnly(), str);
if (!result) {
FAIL_IC();
}
- WRITE_REG(strId.id(), reinterpret_cast<uint64_t>(result), STRING);
+ WRITE_REG(resultId.id(), reinterpret_cast<uint64_t>(result), STRING);
DISPATCH_CACHEOP();
}
diff --git a/js/src/jit-test/tests/cacheir/bug2079040.js b/js/src/jit-test/tests/cacheir/bug2079040.js
new file mode 100644
index 00000000000..38322951360
--- /dev/null
+++ b/js/src/jit-test/tests/cacheir/bug2079040.js
@@ -0,0 +1,40 @@
+function f(o, a, b, h1, h2) {
+ var k = a + b;
+ h1.w = k;
+ var r = o.hasOwnProperty(k);
+ h2.x = k;
+ return r;
+}
+with ({}) {}
+var N = 9000;
+var hs1 = [], hs2 = [];
+for (var i = 0; i < N; i++) {
+ hs1.push({a: i});
+ hs2.push({a: i});
+}
+var objs = [];
+for (var i = 0; i < 5; i++) {
+ var o = {};
+ o["p" + i] = 1;
+ objs.push(o);
+}
+var small = {abcdefgh1: 1, abcdefgh2: 2};
+gc();
+for (var i = 0; i < N; i++) {
+ var o = small, b = "h1";
+ if (i >= 600 && i < 603) {
+ o = "primitive";
+ } else if (i >= 6000 && i < 6005) {
+ o = objs[i - 6000];
+ } else if (i >= 6005) {
+ b = "h2";
+ }
+ f(o, "abcdefg", b, hs1[i], hs2[i]);
+}
+minorgc();
+var sum = 0;
+for (var i = 6006; i < N; i++) {
+ var s = hs2[i].x;
+ sum += s.length + s.charCodeAt(0);
+}
+assertEq(sum, 317364);
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/js/src/jit-test/tests/cacheir/bug2079040.js b/js/src/jit-test/tests/cacheir/bug2079040.js
new file mode 100644
index 00000000000..38322951360
--- /dev/null
+++ b/js/src/jit-test/tests/cacheir/bug2079040.js
@@ -0,0 +1,40 @@
+function f(o, a, b, h1, h2) {
+ var k = a + b;
+ h1.w = k;
+ var r = o.hasOwnProperty(k);
+ h2.x = k;
+ return r;
+}
+with ({}) {}
+var N = 9000;
+var hs1 = [], hs2 = [];
+for (var i = 0; i < N; i++) {
+ hs1.push({a: i});
+ hs2.push({a: i});
+}
+var objs = [];
+for (var i = 0; i < 5; i++) {
+ var o = {};
+ o["p" + i] = 1;
+ objs.push(o);
+}
+var small = {abcdefgh1: 1, abcdefgh2: 2};
+gc();
+for (var i = 0; i < N; i++) {
+ var o = small, b = "h1";
+ if (i >= 600 && i < 603) {
+ o = "primitive";
+ } else if (i >= 6000 && i < 6005) {
+ o = objs[i - 6000];
+ } else if (i >= 6005) {
+ b = "h2";
+ }
+ f(o, "abcdefg", b, hs1[i], hs2[i]);
+}
+minorgc();
+var sum = 0;
+for (var i = 6006; i < N; i++) {
+ var s = hs2[i].x;
+ sum += s.length + s.charCodeAt(0);
+}
+assertEq(sum, 317364);
Loading diff…
References
On This Page