java-topology/whitepaper/outreach/spidermonkey.md

5.1 KiB
Raw Blame History

SpiderMonkey (Firefox JavaScript Engine) — CWE-407 Disclosure Brief

2026-03-27 · Patch available — awaiting upstream merge

Finding

One O(N×T) defect in SpiderMonkey's IonMonkey JIT compiler — in the LinearSum::add() function used during Ion bounds-check elimination. Patched. Patch ready for upstream review.

The Defect

spidermonkey-0001 (PATCHED — HIGH): js/src/jit/IonAnalysis.cpp:~1997

// In LinearSum::add() — Ion bounds-check elimination analysis:
// Called for every add/subtract expression in JIT-compiled functions:
bool LinearSum::add(TermVector& terms, int32_t scale, MDefinition* term) {
    for (size_t i = 0; i < terms.length(); i++) {
        if (terms[i].term == term) {      // O(T) — Vector linear scan per add()
            // combine existing term with same definition
            terms[i].scale += scale;
            return true;
        }
    }
    // not found — append new term
    return terms.append(LinearTerm(term, scale));
}

TermVector is Vector<LinearTerm, 2> (SpiderMonkey's arena-allocated vector). The membership check terms[i].term == term is a linear scan over T terms per add() call. For N add() / subtract() operations in a function: O(N × T) total.

The main IonMonkey paths use js::HashSet/HashMap correctly for graph traversal. sm-0001 is specifically in the Ion analysis pass that runs bounds-check elimination — the pass that eliminates array bounds checks in hot loops.

Complexity Proof

For N add/subtract operations in a function and T distinct terms in the linear sum:

  • Per add() call: O(T) linear scan over terms vector
  • Total: O(N × T)

At N=1,000 additions, T=50 distinct terms: defective=50,000 comparisons, fixed=1,000 (HashMap<MDefinition*, int32_t> lookup). 50× speedup.

Bounds-check elimination is particularly important for tight inner loops — array processing, typed array operations, canvas rendering, WebGL vertex processing. These are exactly the code patterns where T (distinct array bases) grows and N (indexing operations) is large.

Impact

SpiderMonkey is Firefox's JavaScript engine. Firefox has ~250M active users. SpiderMonkey's IonMonkey tier compiles hot JavaScript functions for maximum performance.

sm-0001 fires in the bounds-check elimination analysis pass — a core optimization that enables tight array loops to run without redundant bounds checks. This affects:

  • Web applications with typed array heavy workloads (WebGL, WebAudio, canvas 2D)
  • JavaScript benchmarks and performance-critical web applications (games, visualizations)
  • Firefox DevTools — JavaScript profiler and debugger run through SpiderMonkey
  • Node.js alternative use cases — some SpiderMonkey embeddings for server-side use

Functions with many distinct array variables (multiple typed arrays processed in a single loop) maximize T. Tight inner loops with many index operations maximize N. WebGL rendering shaders and image processing code are worst case.

The Ion JIT tier compiles frequently-called JavaScript functions. A function called millions of times in a render loop is compiled once by Ion but benefits from the bounds-check elimination pass running at O(N) instead of O(N×T) — faster compilation means lower JIT latency and faster time-to-peak-performance.

The Fix

Replace Vector<LinearTerm, 2> + linear scan with HashMap<MDefinition*, int32_t>:

// Before
bool LinearSum::add(TermVector& terms, int32_t scale, MDefinition* term) {
    for (size_t i = 0; i < terms.length(); i++) {
        if (terms[i].term == term) {      // O(T) linear scan
            terms[i].scale += scale;
            return true;
        }
    }
    return terms.append(LinearTerm(term, scale));
}

// After
// CWE-407 fix: HashMap<MDefinition*, int32_t> for O(1) lookup instead of O(T) scan.
bool LinearSum::add(TermMap& termMap, int32_t scale, MDefinition* term) {
    auto result = termMap.lookupOrAdd(term, scale);
    if (!result) return false;
    if (result->found()) {
        result->value() += scale;
    }
    return true;
}

js::HashMap<MDefinition*, int32_t> is already available in SpiderMonkey's own container library and uses SpiderMonkey's arena allocator.

Patch

Fix available: defects/spidermonkey/patch/spidermonkey-0001-linearsum-hashmap.patch

Single-function change in js/src/jit/IonAnalysis.cpp.

Unit test: O(N×T) → O(N) growth confirmed. Speedup measured on JIT-compiled functions with many distinct typed array bases.

What We Ask

A patch is ready for review.

  1. Confirm receipt and assign a Mozilla Bugzilla reference (bugzilla.mozilla.org, component: Core :: JavaScript Engine: JIT).
  2. Assess severity — sm-0001 fires in bounds-check elimination for every Ion-compiled function with multiple array variables; WebGL and typed array heavy workloads are worst case.
  3. Coordinate a disclosure date — we are targeting 90 days from first contact.
  4. We will credit the SpiderMonkey/Mozilla team in the public disclosure. Preferred acknowledgment format welcome.

Contact: see cover email. This brief is confidential until coordinated disclosure.