Closed Bug 1841400 Opened 2 years ago Closed 2 years ago

Unexpected behavior in optimization causing altered output of JavaScript array operations

Categories

(Core :: JavaScript Engine, defect)

Firefox 116
defect

Tracking

()

RESOLVED INVALID

People

(Reporter: 0x4248, Unassigned)

Details

Attachments

(2 files)

Steps to reproduce:

Tested on:

Stable 114.0.2
Beta 115.0
Developer 115.0b9
Nightly 116.0a1

To reproduce the problem, follow the steps below:

  1. Open the attached HTML file (check_20230702_1074028.html).
  2. Observe the output is false after the script completes its iterations.

or

Execute the following JavaScript code on the Firefox console or shell:


    function opt(){
      const v1 = [];
      v1[127] = Uint8Array;
      const v9 = v1.includes();
      let v10 = 0;
      while (v10 < 10) {
          const v13 = [[],v9];
          const v14 = v13.push;
          const v15 = v13.__proto__;
          const v16 = v13.map(v14,v15);
          const v17 = v10++;
      }
      return v9;
    }

    console.log(opt());

    for(let i=0;i<0xffff;i++){ opt(); }
    console.log(opt());

Upon execution, the initial call to opt() should return true, as expected. However, after invoking opt() through a large number of iterations, the opt() function unexpectedly returns false.

Actual results:

Upon execution of the JavaScript function opt(), the function call initially returns true as expected. However, the function's return value changes to false after it's invoked repeatedly through iterations. This change in output is inconsistent and unexpected.

Expected results:

Regardless of the number of iterations or invocations, the function opt() should consistently return true as per its original definition and behavior. The function's return value should not change or become inconsistent due to repeated invocations.

Upon conducting additional tests, it appears that this potential bug is not limited to the SpiderMonkey. The issue also manifests in other major browsers, including Chrome and Safari, suggesting it might be inherent to the JavaScript language or to the common JIT optimization techniques used across engines. Nonetheless, a more comprehensive investigation is necessary to ascertain the cause of this issue.

Summary: Unexpected behavior in V8 JIT optimization causing altered output of JavaScript array operations → Unexpected behavior in optimization causing altered output of JavaScript array operations
Group: firefox-core-security → javascript-core-security
Component: Untriaged → JavaScript Engine
Product: Firefox → Core

Andrew got results changing to false after about 4 or 5 manual calls to "opt()" in the devtools web console, so might have nothing to do with the jit and something to do with side-effects to __proto__. or would the while loop inside opt() itself get jitted after a certain amount of use? very odd.

The test can be simplified to the one below. When opt is called, it adds elements to Array.prototype. This affects the result of includes() called on an array with holes because after a few calls to opt we've added enough elements to the prototype (more than about 127) that we no longer get undefined for any of the holes in the array because they now all resolve to properties on the array prototype.

function opt(){
  const v1 = [];
  v1[127] = 1;
  const v9 = v1.includes(undefined);
  for (let i = 0; i < 10; i++) {
    Array.prototype.push([], 0, []);
    Array.prototype.push(v9, 1, []);
  }
  return v9;
}
for (var i = 0; i < 5; i++) {
  console.log(opt());
}
Status: UNCONFIRMED → RESOLVED
Closed: 2 years ago
Resolution: --- → INVALID

(In reply to 이준성(Junsung Lee) from comment #1)

Upon conducting additional tests, it appears that this potential bug is not limited to the SpiderMonkey. The issue also manifests in other major browsers, including Chrome and Safari, suggesting it might be inherent to the JavaScript language or to the common JIT optimization techniques used across engines. Nonetheless, a more comprehensive investigation is necessary to ascertain the cause of this issue.

If you get the same result with other JS engines too, it's a very strong sign that it's likely an issue with the test case and not a bug in the browser. It's possible that multiple engines have the same bug, but it's pretty uncommon especially when you're testing these older array builtins.

Group: javascript-core-security

(In reply to Jan de Mooij [:jandem] from comment #3)

The test can be simplified to the one below. When opt is called, it adds elements to Array.prototype. This affects the result of includes() called on an array with holes because after a few calls to opt we've added enough elements to the prototype (more than about 127) that we no longer get undefined for any of the holes in the array because they now all resolve to properties on the array prototype.

I greatly appreciate your comprehensive clarification!

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: