3 Commits
Author SHA1 Message Date
zeekayandHanzo Dev f9909a847a builder: eager-reserve + value ObjectBuilder — zero-defer, zero OB alloc
Decomplect that unlocks a perf win. SetBytes deferred its data into an offsets
[]offsetEntry slice replayed in Finish — machinery that recorded intentions to
replay later, and heap-allocated a slice per object-with-a-bytes-field. Replace
it with directness: StartObject RESERVES the fixed section eagerly, so SetBytes
appends its tail + patches its own pointer on the spot; Finish just returns the
offset. Removing the offsets field makes ObjectBuilder's methods mutate only
ob.b (through the pointer) and never ob itself — so ObjectBuilder becomes a
VALUE type and StartObject stops heap-allocating &ObjectBuilder per call (it was
65% of composite-build allocs).

Byte-identical wire (golden + fuzz + pool byte-equality + nested-proof suites all
green). Real X-tx wire composite: 922ns/11allocs -> 655ns/5allocs (1.4x, <half
the allocs); vs the original byte-blob 2551ns/37allocs that's 3.9x / 7.4x fewer
allocs. Speeds EVERY zap object build node-wide, not just X.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-14 09:34:28 -07:00
Hanzo AI 3fac1c82bf feat(zap): v0.7.2 — Object.ListStride per-stride clamp + List.Len SAFETY doc + FuzzParse
LP-023 Red round 3 follow-ups:

NEW-V1 follow-up: tighter per-element stride clamp via Object.ListStride.
The bare Object.List uses the permissive `length <= len(data)` baseline
(wire layer cannot know per-accessor stride). Callers that know the
element width can opt into the tighter `length * minStride <= bufRem`
clamp via ListStride(off, stride), rejecting poisoned length values up
front instead of relying on per-element bounds checks.

NEW-V1 docstring: List.Len() now carries the SAFETY caveat — callers MUST
NOT pre-allocate via make([]T, l.Len()) without an independent bound.

FuzzParse (Red follow-up #3): round-trip property fuzzer pinning the
Parse↔Bytes contract: msg.Bytes() == data[:msg.Size()], Parse is
idempotent on its own output, Version() always in {Version1, Version2}.
1M+ execs clean on M1 Max with 20s fuzztime; seed corpus includes
adversarial buffers that exercised RED-HIGH-1/2/3.

Tests:
- TestNewV1_ListStrideTighterClamp — poisoned length=100 passes bare
  baseline but ListStride(0, 4) rejects (400 > bufRem)
- TestNewV1_ListStrideAcceptsHonestLength — honest length=5 stride=4
  buffer must pass

All existing tests still pass (RedRound2 HIGH-1/2/3, MEDIUM-1, V18 + base).

Wire format unchanged — purely a tightened acceptance test; backward
compatible at the wire level. Callers update obj.List(off) →
obj.ListStride(off, minStride) per element type.
2026-06-02 15:31:41 -07:00
Hanzo AI ba30b4b73d chore: sync latest 2026-04-09 18:44:08 -07:00