Skip to content

security: validate result shapes, bound empty-array work, guard every asm call; go 1.26.6 - #24

Merged
tannevaled merged 4 commits into
mainfrom
audit/security-2026-10-04
Oct 4, 2026
Merged

tannevaled merged 4 commits into
mainfrom
audit/security-2026-10-04

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

Security audit, 2026-10-04. Full write-up in SECURITY.md.

Found and fixed

  • Concatenate summed axis lengths without an overflow check: 17 arrays (2^59, 0) gave a negative dimension. Fixed with a checked sum, plus validateShape on the result. This also covers Stack, which used to return (9, 2^58, 0), a shape New rejects.
  • MatMul/Dot/Inner of (m, 0) @ (0, n) never validated m*n. (2^32,0)@(0,2^32) returned a (2^32, 2^32) array with Size() == 0; a product wrapping to −1 panicked in makeslice. Both are now ErrShapeMismatch.
  • Linspace(…, 1<<62) panicked in makeslice; it now returns ErrShapeMismatch.
  • Effective hangs (DoS) on empty arrays with a huge axis. Reducing (2^58, 0) over axis 0, concatenating it along its last axis, or CumSum of (0, 2^58) walked 2^58 iterations doing nothing. The kernel is now skipped when the result is empty.

Hardened

  • Every Go wrapper around an assembly kernel (amd64, arm64, ppc64le, loong64) indexes the last element the kernel will touch in each operand. A caller's mistake becomes a Go index panic instead of an out-of-bounds access in assembly. TestWrappersRefuseShortOperands checks this; sabotaging one guard makes it fail.
  • New fence_test.go: each operand is mmap'd flush against a PROT_NONE page, both head and tail, for n = 1…70 and GEMM kc = 1…9, and the FMA/LASX fallbacks run too. It passes on real amd64 (Zen 3), arm64 (cfarm185 + M-series), ppc64le (POWER9) and loong64 (3C5000L, LASX). Positive control: a kernel reading one element too far faults on all four page sizes (4K/16K/16K/64K).

Other

  • go 1.26.6 (root and generator module). govulncheck at 1.26.4 listed 10 stdlib vulns (none reachable); at 1.26.6 there are none. Regenerated .s are byte-identical on all 4 arches.
  • Private vulnerability reporting is enabled on the repo, as SECURITY.md says.
  • Untracked 4 coverage profiles (cg*.out, cover2.out) that had been committed; *.out is now ignored.
  • README: SIMD now ships on amd64/arm64/ppc64le/loong64 (the text said amd64+arm64); new "Untrusted input" section.

Cost

On a single Zen 3 core, an A/B of 10 interleaved rounds: MatMul 256², Dot1D and AddInto 16Ki all fall within ±2%, which is inside the spread between runs.

Version: v0.3.0. The minimum Go version goes up, and some calls now return errors where they used to return arrays.

🤖 Generated with Claude Code

tannevaled and others added 4 commits October 4, 2026 20:54
…d asm operands

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e profiles

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit 60c7c54 into main Oct 4, 2026
12 checks passed
@tannevaled
tannevaled deleted the audit/security-2026-10-04 branch October 4, 2026 19:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant