Bug 1801794 Comment 7 Edit History

Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.

Looking at `PrimitiveValueToId`, we only call `PrimitiveValueToIdSlow` for an Int32 [if the index is negative](https://searchfox.org/mozilla-central/source/js/src/vm/JSAtom-inl.h#67).  So presumably this code is using a lot of negative indices.

I took a look at the source code, which I think has been minified by hand as a demo. Pulling out the core code and adding enough definitions to get it to run, I get this:

```
Looking at `PrimitiveValueToId`, we only call `PrimitiveValueToIdSlow` for an Int32 [if the index is negative](https://searchfox.org/mozilla-central/source/js/src/vm/JSAtom-inl.h#67).  So presumably this code is using a lot of negative indices.

I took a look at the source code, which I think has been minified by hand as a demo. Pulling out the core code and adding enough definitions to get it to run, I get this:

```
var c = {
  fillRect: function() {},
  clearRect: function() {},
  beginPath: function() {},
  lineTo: function() {},
  fill: function() {},
}

var a = {
  width: 15, // **** THIS IS THE KEY ****
  height: 15,
  style: {
    background: undefined
  }
}

var count = 0;
function requestAnimationFrame(f) {
  if (count++ < 100) f(count * 2000)
}
// everything below this line is original

function f(a) {
    for (a /= 1e3, c.clearRect(0, 0, W, H), c.fillStyle = "#FFF", o = ~~(a / (M > 1 ? 9 : 2) * W) % W, Z[0] = [], i = 1; i < 4; ++i)
        for (j = 0; j < W; ++j) k = j - o, k < 0 && (k += W), x = k / i | 0, y = Z[i][j] / i, Z[0][x] < y || (Z[0][x] = y);
  for (i = W; i;) {
        if (!(M % 2)) {
          for (X = [], Y = [], z = l = 0, j = 3; j--; i--) k = i - (M > 1 ? o : 0), k < 0 && (k += W), k && (X[j] = k, Y[j] = Math.tan(i % 99 * i + a) * H / 8 + H / 8, Y[j] > z && (z = Y[l = j]));
          Y[l] > Z[0][i] && (Y[l] = Z[0][i])

        }
        for (c.beginPath(), j = 3; j--;) M % 2 ? (k = i - (M > 1 ? o : 0), k < 0 && (k += W), k && (z = Math.tan(i % 99 * i + a) * H / 8 + H / 8, z > Z[0][i] && (c.fillRect(k, z, 2, 2), z = Z[0][i]), c.lineTo(k, z)), i--) : c.lineTo(X[j], Y[j]);
        c.fill()
    }
    requestAnimationFrame(f)
}
for (R = Math.random, W = a.width, H = a.height, a.style.background = "#000", Z = [], i = 1; i < 4; ++i)
    for (Z[i] = [], x = y = 0, j = 0; j < W; ++j) j == x && (x += R() * W / 8 + W / 8 | 0, y = y ? 0 : R() * H / 4 + H / 4), Z[i][j] = H - y;
M = 0, a.onclick = function() {
    ++M, M > 3 && (M = 0)
}, f();
```
I didn't immediately see where the negative indices were being used, so I tried running it. Interestingly, although the original webpage works fine for me, this code got stuck in an infinite loop. After debugging it for a bit, I realized that `i` was becoming increasingly negative in the `for (i = W; i; )` loop. The values of `i` were decreasing by 3 each iteration. By setting the initial value of `a.width` to a multiple of 3, everything worked out.

It looks like `a` is initialized here: `k=g.createElement("iframe");g.body.appendChild(k);var a=k.contentWindow`. So it's the width of the iframe. If it's a multiple of 3, then this code works. Otherwise, it gets caught in an infinite loop.

Looking at the webpage in devtools, the canvas width is 1920, which is also the horizontal resolution of my laptop display. If I temporarily change the resolution to 1600x900, which is not divisible by 3, the demo hangs.

So the bug appears to be in the webpage, not Firefox.

Back to Bug 1801794 Comment 7