Skip to content

JSON.stringify panics on arrays of ~30k+ records with nested objects #43

Description

@proggeramlug

Repro

const arr: any[] = [];
for (let i = 0; i < 30000; i++) {
  arr.push({
    id: i,
    name: 'Record ' + i,
    email: 'r' + i + '@example.com',
    age: 18 + (i % 70),
    addr: { street: i + ' Main St', city: 'Springfield', zip: 10000 + i },
  });
}
const text = JSON.stringify(arr);  // ← panic here
console.log('input bytes:', text.length);

Actual (Perry 0.5.30)

thread '<unnamed>' (...) panicked at crates/perry-runtime/src/json.rs:427:36:
byte index 3 is not a char boundary; it is inside '\0' (bytes 2..3) of
`� � �� � �X � � � �� � ��^I � �X
 � � � �� � �� � �X � � � �� � �� � �X…`

Expected

Serializes the array, prints input bytes: 5444780 (or similar).

Observations

  1. Works cleanly up to ~20k records with this object shape.
  2. The panic message shows garbage bytes — the stringifier is reading past the valid UTF-8 range of a string payload. Probably a length / capacity confusion in StringHeader, or a Buffer-vs-String header mix-up.
  3. The panic is in perry-runtime/src/json.rs:427 calling .is_char_boundary() on a non-UTF-8 byte range.
  4. The threshold depends on object shape, not just record count — flat {id, active} objects work at 500k records; adding nested .addr pushes the breakpoint down to ~30k.

Probably the same underlying data corruption as #42 (large Buffer param) and #[JSON.parse+iterate issue], just surfacing in the stringify path.

Impact

Any program that produces a JSON document larger than ~6 MB from TS-side data will hit this.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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