Incorrect truncation after folding away fallible unbox
Categories
(Core :: JavaScript Engine: JIT, defect, P1)
Tracking
()
| Tracking | Status | |
|---|---|---|
| firefox90 | --- | fixed |
People
(Reporter: troya, Assigned: iain)
Details
(Keywords: reporter-external, Whiteboard: [reporter-external] [client-bounty-form] [verif?])
Attachments
(1 file)
VULNERABILITY DETAILS
The following PoC generates a Firefox JIT incorrect optimization of typed array values, which leads to optimized function return value to be different than unoptimized function return value, similarly to a Chrome bug: https://bugs.chromium.org/p/chromium/issues/detail?id=880207
VERSION
Firefox Version: 88.0 64 bits + Stable
Operating System: Windows 10 x64 + Linux Ubuntu 20 x64
REPRODUCTION CASE
z = (a)=>{let m = new Uint32Array([-1]); let h = m[0]; let r = m[0]; if (a) h = undefined; if (a) r = 0xff; return h > r}
console.log(z(false)) //prints false
for (let i = 0; i < 0x5000; ++i) z(true)
console.log(z(false)) //prints true
ADDITIONAL INFORMATION
Type of bug: optimized function return value is different than unoptimized
on Linux Ubuntu 20 x64 at ./js interpreter: optimized function return value is different than unoptimized
on Windows 10 x64 at Firefox Browser: optimized function return value is different than unoptimized
CREDIT INFORMATION
Reporter credit: Jose Martinez tr0y4 from VerSprite Inc.
Updated•4 years ago
|
Comment 1•4 years ago
|
||
Thanks for the bug report!
Simplified test below. Iain, can you take a look? It seems related to the RA truncation code.
function f(a) {
let m = new Uint32Array([-1]);
let h = m[0];
let r = m[0];
if (a) {
h = undefined;
}
if (a) {
r = 0xff;
}
return h > r;
};
assertEq(f(false), false);
for (let i = 0; i < 0x5000; ++i) {
f(true);
}
assertEq(f(false), false);
| Assignee | ||
Comment 2•4 years ago
|
||
The good news is that I'm pretty sure this is another example of a bug where we recover the wrong result on bailout, but it's not a security issue, because baseline works with untyped values.
The bug occurs in the handling of h > r. We transpile the following CacheIR:
GuardIsUndefined inputId 0
GuardIsNumber inputId 1
LoadBooleanResult val false
ReturnFromIC
which produces MIR like this:
56 phi constant53:Int32 loadUnboxedScalar46:Double
57 guardValue phi51:Value
58 unbox phi56 to Double (fallible)
59 constant false
Note that the loadUnboxedScalar for m[0] has MIRType::Double because Int32 can't represent values greater than 0x7fffffff. Note also that neither of the operands is marked as implicitly used, because the guards are explicit uses.
When we apply type policies, phi56 is assigned MIRType::Double. We then insert box phi56:Double before unbox58, because it expects a boxed operand. Later, GVN sees that we are boxing and unboxing a double value, and removes both instructions. But now phi56 has no non-resume-point uses, and since it isn't marked as a guard / implicitly used, range analysis decides that we can truncate it.
I think the problem here is that phi56 is not marked as implicitly used. The simplest fix might be in MUnbox::foldsTo: if we fold MUnbox(MBox(x)) => x, and the unbox is fallible, marking x as implicitly used fixes the problem.
| Assignee | ||
Comment 3•4 years ago
|
||
Updated•4 years ago
|
Updated•4 years ago
|
| Assignee | ||
Comment 4•4 years ago
|
||
Opening this up and renaming it because it's not a security issue.
We talked about this in the Warp meeting earlier today. The current fix is a bit ad-hoc, but it's not clear what a better approach would be. If similar bugs arise in the future, we will look into the possibility of marking instructions as guards (or implicitly used?) if they are created by the CacheIR transpiler and don't have any other uses, but there's a possibility that this might prevent valid optimizations.
Fortunately the design of Warp means that bugs like this (recovering the wrong value on bailout) aren't exploitable, because we're always recovering to a safe place in baseline, and baseline doesn't make any assumptions based on types.
Comment 6•4 years ago
|
||
| bugherder | ||
Updated•4 years ago
|
Updated•1 year ago
|
Description
•