Closed Bug 1713579 Opened 3 years ago Closed 3 years ago

Assertion failure: Unexpected null or lazy proto in MObjectStaticProto, at jit/VMFunctions.cpp:2805

Categories

(Core :: JavaScript Engine: JIT, defect, P2)

x86_64
Linux
defect

Tracking

()

VERIFIED FIXED
97 Branch
Tracking Status
firefox-esr78 --- unaffected
firefox-esr91 --- wontfix
firefox88 --- wontfix
firefox89 --- wontfix
firefox90 --- wontfix
firefox91 --- wontfix
firefox92 --- wontfix
firefox93 --- wontfix
firefox94 --- wontfix
firefox95 --- wontfix
firefox96 --- wontfix
firefox97 --- verified

People

(Reporter: decoder, Assigned: iain)

References

(Regression)

Details

(5 keywords, Whiteboard: [bugmon:update,bisected,confirmed][adv-main97+r])

Attachments

(3 files)

The following testcase crashes on mozilla-central revision 20210530-1514fcbf80a0 (debug build, run with --fuzzing-safe --cpu-count=2 --ion-offthread-compile=off --baseline-eager --ion-warmup-threshold=0):

var func2 = function (argMath5) {
  for (; b28 < ((this.prop1 ^= (~obj0.prop2))); __loopvar4++ + b28++) {}
}
var b28 = 1;
Object.prototype.prop2 = -1066571423;
__loopvar4 = unescape;
obj0 = unescape;
obj0 = (new func2(1.1));
var func2 = function (argMath5) {
  for (; b28 < ((this.prop1 ^= (~obj0.prop2))); __loopvar4++ + b28++)
    this.prop0 = 1;
}
obj0 = (new func2(1.1));
  func2();

Backtrace:

received signal SIGTRAP, Trace/breakpoint trap.
0x0000327869f5afc2 in ?? ()
#0  0x0000327869f5afc2 in ?? ()
#1  0x0000327869eda815 in ?? ()
#2  0x0000000000001044 in ?? ()
#3  0x00001366c2400658 in ?? ()
#4  0x0000000000000000 in ?? ()
rax	0x20a7caa7f040	35905031630912
rbx	0xfff9800000000000	-1829587348619264
rcx	0xfff9800000000000	-1829587348619264
rdx	0x1	1
rsi	0x0	0
rdi	0x327869eda790	55492754646928
rbp	0x7fffffffb600	140737488336384
rsp	0x7fffffffb570	140737488336240
r8	0x0	0
r9	0xfff9800000000000	-1829587348619264
r10	0xfff9800000000000	-1829587348619264
r11	0x0	0
r12	0x8	8
r13	0x7fffffffbe88	140737488338568
r14	0x1043	4163
r15	0x0	0
rip	0x327869f5afc2	55492755173314
=> 0x327869f5afc2:	push   %rax
   0x327869f5afc3:	movabs $0x7ffff60cd000,%rax

Marking s-s since this is a low-level JIT assert.

Severity: -- → S2
Attached file Testcase (deleted) —
Flags: needinfo?(jdemooij)

We start out with multiple MObjectStaticProto instructions, each with a GuardShape as object operand. Then:

  • In MGuardShape::foldsTo, we decide to optimize away a shape guard (because we see we added a property to the same object and as part of that we must have changed the object's shape to the same shape).
  • As a result, one of the MObjectStaticProto instructions now has an object Phi as input and is hoisted by LICM, because we know adding a property doesn't mutate the prototype.
  • We then assert in codegen because the object is the WindowProxy which has a lazy proto.

I think the root cause is that the logic in MGuardShape::foldsTo is a bit of a hack that doesn't really belong in GVN. We probably want a dedicated analysis pass for this that runs later, similar to FoldLoadsWithUnbox and EliminateRedundantChecks.

This can likely trigger near-null crashes in release builds (for example in GC), but I don't think it's sec-high or sec-critical. Best to leave it hidden for now though.

Reduced test case:

function f() {
	var i = 0;
	while (i < (this.foo = this.foo ^ 123)) {
		this.prop = 1;
	}
}
new f();
f();

Bugmon Analysis:
Verified bug as reproducible on mozilla-central 20210531115711-fafcc4a3b16a.
The bug appears to have been introduced in the following build range:

Start: f4af0087a1b49c221f54143a10b7bebca35db49c (20210111195436)
End: febd0fad07331284c49334bab4d9c653f2c80275 (20210111195806)
Pushlog: https://hg.mozilla.org/integration/autoland/pushloghtml?fromchange=f4af0087a1b49c221f54143a10b7bebca35db49c&tochange=febd0fad07331284c49334bab4d9c653f2c80275

Whiteboard: [bugmon:update,bisect] → [bugmon:update,bisected,confirmed]
Has Regression Range: --- → yes
Keywords: sec-audit
Priority: -- → P2

This patch takes the code from MGuardShape::foldsTo and splits it out into its own optimization. Besides jitspew, the main change is adding support for MNewPlainObject (which didn't exist when this code was first written.)

We use dependency() to find the most recent store. It is possible for a node's dependency to be in a dead block. In ValueNumberer::visitDefinition, we check for this case; I used the same approach here.

Assignee: nobody → iireland
Status: NEW → ASSIGNED
Attached file Bug 1713579: Add testcase r=jandem (deleted) —

Depends on D133129

Group: javascript-core-security → core-security-release
Status: ASSIGNED → RESOLVED
Closed: 3 years ago
Resolution: --- → FIXED
Target Milestone: --- → 97 Branch

Bugmon Analysis
Verified bug as fixed on rev mozilla-central 20211209093228-3f29a100ee06.
Removing bugmon keyword as no further action possible. Please review the bug and re-add the keyword for further analysis.

Status: RESOLVED → VERIFIED
Keywords: bugmon
Regressions: 1745388

Is this something we should consider backporting?

Flags: needinfo?(iireland)

No, this can and should ride the trains. We don't think this is exploitable.

Flags: needinfo?(jdemooij)
Flags: needinfo?(iireland)
Whiteboard: [bugmon:update,bisected,confirmed] → [bugmon:update,bisected,confirmed][adv-main97+r]
Flags: in-testsuite+
Regressions: 1776356
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: