frostney / frostney/GocciaScript

Array copy-constructors preallocate guest-sized element capacity with no budget consult

Open
#1,173 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug engine
Dominant language
Pascal
Stars
20
Forks
3
Avg merge
3d 4h
Merged PRs (30d)
45

Description

Summary

Element-list capacity is guest-sizable with no budget consult at all on the array-copy constructors: Array.prototype.toSpliced.call({length: N}, 0, 0) allocates an N-slot element list (TGocciaArrayValue.Create(nil, NewLenInt)FElements.Capacity := N) bounded only by CheckArrayCreateLenValue (≤ MaxInt), never by --max-memory.

Why

Runtime-confirmed during the #1157 rooting train's L3 review (2026-08-16): Array.prototype.toSpliced.call({length: 200000}, 0, 0) returns a 200,000-slot array with zero gate consultations. At the permitted ceiling that is a 2^31-1-pointer (~16 GiB on 64-bit) allocation request the budget never sees — the same uncharged-native-storage class ADR 0106 records for gated growth, except this path has no gate either. The growth gate (RequireNativeBytes via ExtendElementsWithHoles) bounds hole extension; capacity preallocation through the constructor bypasses it.

Current behavior

ArrayToSpliced (source/units/Goccia.Values.ArrayValue.pas ~:3645) and sibling copy-constructors (toReversed, toSorted — audit which share the constructor-capacity path) size FElements.Capacity directly from a guest-controlled length under a --max-memory ceiling that never sees the request.

Expected behavior

Constructor-capacity preallocation from guest-controlled lengths consults the element-storage gate (TGocciaElementList.RequireStorageBytes, in place since the rooting train's L3) or an equivalent budget check before Capacity := N, refusing with the uncatchable MemoryLimitError per the gate contract. Coverage: a test at a tight ceiling asserting the refusal, plus the existing suites green.

Scope notes

  • Pre-existing on main; independent of the #1157 train (found by its L3 review, not introduced there).
  • Related: ADR 0106 (uncharged gated storage posture), the #1157 train's L2/L3 gate-side rooting (the gate to reuse), CheckArrayCreateLenValue.
  • The new Array(n) constructor path IS gated (via InitializeNativeFromArgumentsExtendElementsWithHoles); this issue is about the capacity-preallocation path that skips it.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in source/units/Goccia.Values.ArrayValue.pas around ArrayToSpliced (~:3645), then audit the toReversed and toSorted copy-constructor paths and the TGocciaElementList.RequireStorageBytes gate. Add coverage using a tight memory ceiling and verify guest-controlled capacity preallocation is refused with MemoryLimitError; run the existing suites afterward.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.