Skip to content

uci-comb has no offline handshake rig — rig_https_local cannot allocate scratch on it #209

Closed

Description

@JC-000

tools/uci/rig_https_local.py cannot run against the uci-comb product on either tree. It dies in MemoryArbiter.alloc before touching the device, so c64-https-uci-comb.prg — the fastest shipped product — can be handshake-tested only against the live internet, via rig_https_banner.py.

Measured, master 48657f5, PRG 5aa224d455fb4d355150896ee33fa2c9ae2faf18f113339b75c9ddc087cab9fa (BACKEND=uci USE_NISTCURVES_ONCHIP_COMB=1 HTTPS_SNI=www.foo.invalid):

  File "tools/uci/rig_https_local.py", line 1412, in main
    ROUTINE_ADDR    = arbiter.alloc(256, name="trampoline")
c64_test_harness.memory_arbiter.MemoryArbiterError: MemoryArbiter.alloc(size=256, alignment=1, name='trampoline') found no free range.
Trace:
  free $5F71-$5FFF (143 B) too small for 256 B @ alignment 1

The rig needs 387 B (256 trampoline + 64 host_str + 64 path_str + 3 one-byte sentinels). Available in the CRYPTO_OVERLAY tail:

tree last segment tail free needed
master 48657f5 LIB_NISTCURVES_MUL_CODE ends $5F70 $5F71-$5FFF 143 B 387 B
e4fda6d LIB_NISTCURVES_MUL_CODE ends $5F66 $5F67-$5FFF 153 B 387 B

CLAUDE.md records this hazard at 223 B ("server-name validation took the comb tail from 714 to 223 B"). It has drifted to 143 B and nobody noticed, because the rig has never been pointed at comb: both its docstring and tools/uci/README document its build as USE_NISTCURVES_ONCHIP=1.

A predicted fix was probed and did not deliver. Gating the P-384 objects out of the link (on e4fda6d) was expected to return ~299 B of CRYPTO_AUX_CODE to CRYPTO_OVERLAY. It returns +10 B on uci, because UCI routes CRYPTO_AUX_CODE into NET_CODE, not CRYPTO_OVERLAY — that recovery lands in CRYPTO_OVERLAY only on ip65. Roughly the 33 B of CRYPTO_RODATA reaches the comb tail, minus nistcurves MUL_CODE growth. Do not expect the P-384 lane's retirement to fix this.

Shape of the missing test. A ~40-line monkeypatch of rig_https_local's HTTP_RESPONSE/EXPECTED_BODY — the same override seam rig_https_print_body.py already uses — is enough to drive an offline body test end to end; that throwaway is what produced the measurements in the silent-truncation issue. What is missing is somewhere to put 387 B of scratch under comb, not the test logic.

Activity

  1. JC-000 commented on Sep 8, 2026

    @JC-000
    OwnerAuthor

    The tail figure has moved twice — three numbers are in circulation

    Recording the measured chain so the next person does not re-derive a superseded figure. All three are the same region (CRYPTO_OVERLAY tail on uci-comb), measured at different trees:

    figure where it comes from status
    ~223 B CLAUDE.md stale — predates the libs/nistcurves v0.11.2 → v0.14.0 bump
    153 B measured at 60022de (merged master) superseded
    126 B measured at 7c74b98 (the #211 fix branch, unmerged) current, if that branch lands

    The ~223 was already stale at merged master, independently of anything in #211 — confirmed by rebuilding at 60022de and reading the map.

    The 153 → 126 step is the #211 fix relocating a 27-byte verdict routine into HTTP_AUX_CODE2, which lands in CRYPTO_OVERLAY on both backends. That placement was chosen after two others were rejected: inline in CODE took ip65's LOADER to 0 bytes free, and LOADER_OVERFLOW cost ip65's NET_CODE tail 27 B and broke the wikipedia target by 13 B.

    What this does and does not change here

    It does not make this issue newly true. The rig needs 387 B and could not get it at 223, 153 or 126; rig_https_wiki.py already drives the menu rather than taking arbiter scratch for exactly this reason. The gap is pre-existing and blocking at every one of those figures.

    What it changes is the direction of travel. CRYPTO_OVERLAY is now the documented home for http.s's jsr-only tails on both backends — the segment already holds http_body_done_check and now the truncation verdict. Every future tail comes out of the same budget this issue needs.

    So the practical note for whoever picks this up: if a second http.s tail lands there before this is resolved, check the arbiter before the linker. A placement can link cleanly on the default target and still take the comb tail below what the rigs need — which is a failure that surfaces on hardware, not at build time.

    Related

    The two rejected placements are worth knowing about because both linked cleanly on the default target. Neither PRG size nor "bytes free in the region I touched" would have caught either one; the second only surfaced because someone built the wikipedia target specifically. That rule is now recorded in CLAUDE.md.

  2. JC-000 commented on Sep 25, 2026

    @JC-000
    OwnerAuthor

    Figure update for the tail table above, from #248: on master eed451b (uci-comb PRG 99ca60b2855c88ee53d56982b1653fdd30d82a45e9df373df6cf535fa9e4e7fd) the comb CRYPTO_OVERLAY tail is 126 B (LIB_NISTCURVES_MUL_CODE ends $5F81), still well short of the rig's 387 B. After #248 lands, use python3 tools/measure_margins.py --build --profile uci-comb for the current figure rather than a number written in an issue or in CLAUDE.md.

  3. added 3 commits that reference this issue on Sep 29, 2026
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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions