js/src/jit-test/tests/jaeger/loops/multiply-by-int32min.js

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 function foo()
     2 {
     3   // Range analysis incorrectly computes a range for the multiplication.  Once
     4   // that incorrect range is computed, the goal is to compute a new value whose
     5   // range analysis *thinks* is in int32_t range, but which goes past it using
     6   // JS semantics.
     7   //
     8   // On the final iteration, in JS semantics, the multiplication produces 0, and
     9   // the next addition 0x7fffffff.  Adding any positive integer to that goes
    10   // past int32_t range: here, (0x7fffffff + 5) or 2147483652.
    11   //
    12   // Range analysis instead thinks the multiplication produces a value in the
    13   // range [INT32_MIN, INT32_MIN], and the next addition a value in the range
    14   // [-1, -1].  Adding any positive value to that doesn't overflow int32_t range
    15   // but *does* overflow the actual range in JS semantics.  Thus omitting
    16   // overflow checks produces the value 0x80000004, which interpreting as signed
    17   // is (INT32_MIN + 4) or -2147483644.
    18   //
    19   // For this test to trigger the bug it was supposed to trigger:
    20   //
    21   //   * 0x7fffffff must be the LHS, not RHS, of the addition in the loop, and
    22   //   * i must not be incremented using ++
    23   //
    24   // The first is required because JM LoopState doesn't treat *both* V + mul and
    25   // mul + V as not overflowing, when V is known to be int32_t -- only V + mul.
    26   // (JM pessimally assumes V's type might change before it's evaluated.  This
    27   // obviously can't happen if V is a constant, but JM's puny little mind
    28   // doesn't detect this possibility now.)
    29   //
    30   // The second is required because JM LoopState only ignores integer overflow
    31   // on multiplications if the enclosing loop is a "constrainedLoop" (the name
    32   // of the relevant field).  Loops become unconstrained when unhandled ops are
    33   // found in the loop.  Increment operators generate a DUP op, which is not
    34   // presently a handled op, causing the loop to become unconstrained.
    35   for (var i = 0; i < 15; i = i + 1) {
    36     var y = (0x7fffffff + ((i & 1) * -2147483648)) + 5;
    37   }
    38   return y;
    39 }
    40 assertEq(foo(), (0x7fffffff + ((14 & 1) * -2147483648)) + 5);
    42 function bar()
    43 {
    44   // Variation on the theme of the above test with -1 as the other half of the
    45   // INT32_MIN multiplication, which *should* result in -INT32_MIN on multiply
    46   // (exceeding int32_t range).
    47   //
    48   // Here, range analysis again thinks the range of the multiplication is
    49   // INT32_MIN.  We'd overflow-check except that adding zero (on the LHS, see
    50   // above) prevents overflow checking, so range analysis thinks the range is
    51   // [INT32_MIN, INT32_MIN] when -INT32_MIN is actually possible.  This direct
    52   // result of the multiplication is already out of int32_t range, so no need to
    53   // add anything to bias it outside int32_t range to get a wrong result.
    54   for (var i = 0; i < 17; i = i + 1) {
    55     var y = (0 + ((-1 + (i & 1)) * -2147483648));
    56   }
    57   return y;
    58 }
    59 assertEq(bar(), (0 + ((-1 + (16 & 1)) * -2147483648)));

mercurial