Skip to content

number + typedArray[oob] yields undefined instead of NaN (ToNumber(undefined) not applied in + ) #6884

Description

@proggeramlug

Summary

number + typedArray[<out-of-bounds index>] evaluates to undefined instead of the spec-mandated NaN. The out-of-bounds typed-array element read correctly yields undefined, but the subsequent numeric + fails to ToNumber it (which should give NaN), and the TAG_UNDEFINED sentinel leaks through to the result.

Repro

function readAdd(S: Int32Array, i: number): number {
  return 1000 + S[i];
}
const a = Int32Array.from([10, 20, 30, 40]);
console.log(readAdd(a, 99));  // Node: NaN   Perry: undefined
console.log(readAdd(a, -1));  // Node: NaN   Perry: undefined
console.log(1000 + a[99]);    // Node: NaN   Perry: undefined

node --experimental-strip-types prints NaN for all three; Perry prints undefined.

Scope / notes

  • Pre-existing and independent of any fast path: reproduces regardless of PERRY_TA_PARAM_F64_READ (on and off are bit-exact), i.e. it's present for the plain js_typed_array_get read path on main.
  • Likely in the + lowering / js_dynamic_string_or_number_add handling of an undefined (TAG_UNDEFINED) operand: it should apply ToNumber(undefined) = NaN, not propagate the undefined sentinel. Other numeric ops (-, *) may share the bug (1000 - a[99], 2 * a[99]).
  • String(a[99])"undefined", a[99] === undefinedtrue, and a[99] | 00 are all correct; only the ToNumber-via-arithmetic path is wrong.
  • Found while validating perf(codegen): inline checked-f64 typed-array-param reads in numeric context #6883 (whose gap test deliberately observes OOB reads in === undefined / String() contexts to avoid this unrelated bug). Does not affect bcrypt (_encipher indices are all masked in-bounds).

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