Differential Testing: Different output message involving ArrayBuffer and neuter

VERIFIED FIXED in Firefox 30

Status

()

defect
--
major
VERIFIED FIXED
5 years ago
4 years ago

People

(Reporter: gkw, Assigned: Waldo)

Tracking

(Blocks 2 bugs, {regression, sec-critical, testcase})

Trunk
mozilla32
Points:
---
Dependency tree / graph
Bug Flags:
in-testsuite +

Firefox Tracking Flags

(firefox29 wontfix, firefox30 verified, firefox31+ verified, firefox32+ verified, firefox-esr2430+ fixed, b2g-v1.2 fixed, b2g-v1.3 fixed, b2g-v1.3T fixed, b2g-v1.4 fixed, b2g-v2.0 fixed, seamonkey2.26 wontfix)

Details

(Whiteboard: [adv-main30+][adv-esr24.6+])

Attachments

(3 attachments)

(Reporter)

Description

5 years ago
try {
    Object.defineProperty(this, "x", {
        get: function() {
            return y.length
        }
    })
    z = ArrayBuffer(4)
    y = Int8Array(z)
    z(x)
} catch (e) {}
for (v in x) {}
neuter(z)
print(x)

$ ./js-opt-64-dm-ts-darwin-ebdf2740dc3e --fuzzing-safe --ion-parallel-compile=off test.js
0
$ ./js-opt-64-dm-ts-darwin-ebdf2740dc3e --fuzzing-safe --ion-parallel-compile=off --ion-eager test.js
4

My configure flags are:

CC="clang -Qunused-arguments" CXX="clang++ -Qunused-arguments" AR=ar sh /Users/skywalker/trees/mozilla-central/js/src/configure --target=x86_64-apple-darwin12.5.0 --enable-optimize --disable-debug --enable-profiling --enable-gczeal --enable-debug-symbols --disable-tests --enable-more-deterministic --with-ccache --enable-threadsafe <other NSPR options>

autoBisect shows this is probably related to the following changeset:

The first bad revision is:
changeset:   http://hg.mozilla.org/mozilla-central/rev/6d4ff510c117
user:        Luke Wagner
date:        Thu Oct 24 08:59:59 2013 -0500
summary:     Bug 929786 - Add shell function to neutering (r=sfink)

(s-s because this involves ArrayBuffers)

Since this seems related to ArrayBuffers and neutering, I'm cc'ing the gurus here, Waldo and sfink. (Bug 929786 might just have exposed the issue)

Waldo, is this related?
Flags: needinfo?(jwalden+bmo)
(Assignee)

Comment 1

5 years ago
Cleaner testcase:

  var ab = new ArrayBuffer(4);
  var ta = new Int8Array(ab);
  function q() { return ta.length; }
  q() + q();
  neuter(ab);
  assertEq(q(), 0);

We hit IonBuilder::getTypedArrayLength and inline the typed array's length.  All fine, because when we do that we |obj->setImplicitlyUsedUnchecked();|.  Or is it?

During the neutering operation we call MarkObjectStateChange on the typed array, which *should* throw away the JIT code that inlines the old length.  But if I step into that call a bit, it's clearly not a constraint associated with |obj->setImplicitlyUsedUnchecked()| -- just a TypeCompilerConstraint<ConstraintDataFreezeObjectFlags> watching for the single flag OBJECT_FLAG_UNKNOWN_PROPERTIES (presumably not generated by this code at all).

As far as I can tell, there's no constraint added here that'll cause the inlined typed array length constant to ever be thrown away if the underlying ArrayBuffer is neutered.  And, going back through blame, it looks like "implicitly used" is only relevant for purposes of preserving against DCE seemingly "dead" code to compute the object.  It has *nothing* to do with a constraint watching for typed array/arraybuffer changes at all.

So, this is pretty much bug 982974 comment 33 and bug 982974 comment 43 (responding to that comment).

Taking.  I'll post a fix Monday.
Assignee: nobody → jwalden+bmo
Status: NEW → ASSIGNED
Flags: needinfo?(jwalden+bmo)
OS: Mac OS X → All
Hardware: x86_64 → All
(Assignee)

Comment 2

5 years ago
Posted patch TestSplinter Review
Attachment #8410541 - Flags: review?(sphink)
(Assignee)

Comment 3

5 years ago
Posted patch PatchSplinter Review
The existing watchStateChangeForTypedArrayBuffer is inadequate because of bug 999651.  And really, in this case, we don't really care about the data pointer changing anyway.  Rather, we should just have this case guard on only the length.  (The buffer case perhaps should depend on both, because implicitly it's a constraint that depends on Range(data pointer, length) always being valid.  But that's for bug 999651.)
Attachment #8410544 - Flags: review?(sphink)
Jeff, what security rating should we give this?  sec-high?  Just a leak?
Flags: needinfo?(jwalden+bmo)
(Assignee)

Comment 5

5 years ago
The inlined-constant length can get burned into bounds checks in IonBuilder::jsop_getelem_typed and IonBuilder::jsop_setelem_typed.  If you're careful, it looks like things will fall over accordingly.  That makes this critical.
Flags: needinfo?(jwalden+bmo)
Keywords: sec-critical
(Assignee)

Comment 6

5 years ago
Well, actually.  This only gets used for bounds-checks in conjunction with getTypedArrayElements, which does have a guard in it that detects *some* neutering, per bug 999651.  The object has to be constant for length inlining.  But the data case has an *additional* restriction on when a not-neutered constraint is added -- the typed array data can't be in the nursery.  So *if* the typed array's data is in the nursery, we'll inline a bad length, add no constraint, then load the data pointer out of the object.  Because of the back-neutered-arrays-with-ballast trick from bug 982974, this shouldn't index out of bounds of actual memory (at least, not once bug 999140 lands, and ballasts are used everywhere).  So maybe we are safe here against anything but incorrect results.  Still, I wouldn't want to take that bet unless I absolutely had to.
How far back does this go?
Comment on attachment 8410541 [details] [diff] [review]
Test

Review of attachment 8410541 [details] [diff] [review]:
-----------------------------------------------------------------

I know it's something else, but could you also test a larger (always out-of-line) ArrayBuffer?
Attachment #8410541 - Flags: review?(sphink) → review+
(In reply to Al Billings [:abillings] from comment #7)
> How far back does this go?

Given comment 6, it sounds like it requires GGC (which introduced the nursery), so just to 31? Waldo?
Comment on attachment 8410544 [details] [diff] [review]
Patch

Review of attachment 8410544 [details] [diff] [review]:
-----------------------------------------------------------------

I hate to pile things on someone else, but I'm too unfamiliar with the constraint system to feel confident in my ability to review this.
Attachment #8410544 - Flags: review?(sphink) → review?(shu)
Comment on attachment 8410544 [details] [diff] [review]
Patch

Review of attachment 8410544 [details] [diff] [review]:
-----------------------------------------------------------------

I think we should just use the new ConstraintDataFreezeObjectForTypedArrayData as patched in bug 999651 instead of adding a new constraint just to check the length.

I highly doubt there are real perf gains to separate the two -- if the programmer neutered the array, I see no reason for us to take extra pains to stay in the JIT.
Attachment #8410544 - Flags: review?(shu)
Group: javascript-core-security
(Assignee)

Comment 12

5 years ago
The bad-length visible behavior dates back "a ways".  The wrong code is in mozilla-beta, mozilla-release, and looks to be in b2g18 as well.

As for when bad-indexing happens, less clear.  The GGC aspect of the data-access code doesn't date back so far.  Prior to the GGC conditioning, it looks like bad lengths were inlined unconditionally for any deemed-constant object.  So, GGC doesn't have much of anything to do with this issue, at least sometimes.

The safe inference/assumption is that this needs to be fixed everywhere, I think, with GGC being largely irrelevant to the analysis.
(Assignee)

Comment 13

5 years ago
I'm abandoning the patch (but not the test) here in favor of fixing this as part of bug 999651's ultimate patch.
Depends on: 999651
(Assignee)

Comment 14

5 years ago
Fixed in a mega-rollup patch that also contains bug 999651's fix:

https://hg.mozilla.org/integration/mozilla-inbound/rev/2c631967ab9e

Test not to land yet, probably in a cycle or two.
(Assignee)

Comment 15

5 years ago
Backed out, then relanded with CLOBBER:

https://hg.mozilla.org/integration/mozilla-inbound/rev/57b0932e2f06
https://hg.mozilla.org/mozilla-central/rev/57b0932e2f06
Status: ASSIGNED → RESOLVED
Last Resolved: 5 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla32
Based on comment 9, marking 30 and ESR24 as unaffected.
(Reporter)

Comment 18

5 years ago
(In reply to Lawrence Mandel [:lmandel] from comment #17)
> Based on comment 9, marking 30 and ESR24 as unaffected.

Not true, see:

(In reply to Jeff Walden [:Waldo] (remove +bmo to email) from comment #12)
> The safe inference/assumption is that this needs to be fixed everywhere, I
> think, with GGC being largely irrelevant to the analysis.
Wow. Missed the end of comment 12. Good catch and thanks Gary.

Given that this is sec-critical, we need to consider branch patches. Given where we are in the cycle, the sooner the better but do take the time needed on central as the fix only landed today.
(Assignee)

Comment 20

5 years ago
This is being patched and fixed in bug 999651's work -- fixed on trunk, fixed aurora/beta as of a few minutes ago, and further backports are almost ready to go for approval.
Whiteboard: [adv-main30+][adv-esr24.6+]
Group: javascript-core-security
Hi Gary, any chance you can verify fixed on Fx30 and/or Fx24.6.0esr?
Flags: needinfo?(gary)
(Reporter)

Comment 25

5 years ago
6d4ff510c117 is needed to expose the issue, and this changeset is not present on ESR 24.

neuter now accepts a different number of arguments on mozilla-beta (30), mozilla-aurora (31) and on mozilla-central (32), so the testcases no longer work the way they do. (e.g. now I get "Error: wrong number of arguments to neuter()" on all branches)

Waldo, any idea how the testcases should be changed? Else, we should just consider this fixed and move on.
Flags: needinfo?(gary) → needinfo?(jwalden+bmo)
(Assignee)

Comment 26

5 years ago
Posted patch Updated testSplinter Review
Here's an updated test that deals with bug 999755's addition to all branches.

As I recall, this might have been one of the tests that on the very earliest branches (esr24, maybe b2g26 but I don't think so) I couldn't make fail pre-patch and pass post-patch.  (I suspect because of object-constantizing constraints I didn't have enough knowledge to work through to write a working testcase.  At least, not without spending too much time doing so.)  So this may be unverifiable even with this slightly-updated test.
Flags: needinfo?(jwalden+bmo)
(Reporter)

Comment 27

5 years ago
Thanks Waldo. I'll retry verification again soon. :)
Flags: needinfo?(gary)
(Reporter)

Comment 28

5 years ago
Using Waldo's new tests in comment 26,

I was able to verify a "before (assert) / after (no assert)" situation for aurora (32) due to the original changeset listed in comment 0, rev ebdf2740dc3e, being present.

I was only able to verify "after (no assert)" situations for beta (31) and release (30) due to that changeset not existing on the branches.

Nonetheless, let's assume verified.
Status: RESOLVED → VERIFIED
Flags: needinfo?(gary)
trying to apply this to SeaMonkey 2.26.1 (Gecko 29) resulted in patch conflicts, and due to the nature of this patchset it seems like I won't be able to take it.
Group: core-security
You need to log in before you can comment on or make changes to this bug.