scriggo fork: go-render function index truncates at 256 (int8→uint8) — silent wrong render
Latent correctness bug in the vendored scriggo fork (gitlab.com/haproxy-haptic/scriggo), found while investigating #165 (closed). Not triggered by the bundled chart; filing so it isn't lost. The fix belongs in the fork.
Summary
OpGoRender's function operand is an int8 set from int8(len(currFn.Functions)) and read back as Functions[uint8(a)]. A single compiled template function that references more than 256 distinct parallel-render (go) targets wraps the index modulo 256: targets 0–127 are fine, 128–255 survive the int8→uint8 round-trip, and 256..N wrap to 0..(N−256), rendering the wrong function's body. Output is full-length but silently wrong — no error.
Where (fork, pinned commit 780f57e0)
internal/compiler/emitter_func_store.go:66,74-75—scriggoFnIndexreturnsint8(len(currFn.Functions))and appends, no bound check.internal/compiler/builder_instructions.go:361,364—emitGoRender(f int8, …)stores it inInstruction.A.internal/runtime/run.go:1077,1079—case OpGoRender: fn := vm.fn.Functions[uint8(a)]. (OpGoRenderIndirect, run.go:1100, is register-based and unaffected.)
Reproduction (deterministic, no -race): a go render_glob "partials/*.txt" over 400 files emits 400 OpGoRenders into one function. Build 400 files partials/shard0000..0399.txt each MARKER_NNNN\n, index.txt = {{ go render_glob "partials/*.txt" }}, render once, count each marker. Result on 780f57e0: 144 markers missing, 144 duplicated of 400 — files 256–399 rendered files 0–143 again.
Impact
Latent for the bundled HAPTIC chart — it renders every sharded section with a single macro invoked in a runtime for loop ({% for i … %}{{ go Macro(shard_slice(…)) }}{% end %}), one function index reused each iteration, never >256 distinct targets in one function. It bites any template that fans out go render_glob over >256 files, or writes >256 distinct go Macro() / go render "file" sites in one function/macro.
Fix sketch
Widen the parallel-render function operand beyond int8 (the instruction already spans two words), or bound-check in scriggoFnIndex and fail the build with a clear "too many parallel-render targets in one function" error. A build-time hard error is the floor; the silent modulo is the dangerous part.