Skip to content

fix: guard compiler registration and golden writing - #321

Merged
OmarAlJarrah merged 1 commit into
mainfrom
fix/engine-irtest-boundary-assertions
Aug 9, 2026
Merged

fix: guard compiler registration and golden writing#321
OmarAlJarrah merged 1 commit into
mainfrom
fix/engine-irtest-boundary-assertions

Conversation

@OmarAlJarrah

Copy link
Copy Markdown
Member

Summary

compilers.Registry.Register called c.Formats() on its argument before checking
anything, so registering a nil compiler was a nil dereference raised inside the
package rather than an error the caller could handle. engine.NewWith(nil)
segfaulted:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x20]
compilers.(*Registry).Register(...) compilers/compilers.go:58
engine.NewWith(...) engine/engine.go:52

Issue #89 assumed the opposite. It lists Registry.Register among the boundaries
that "all guard their inputs" and asks only for a nil guard on
engine.NewWithRegistry. Neither half holds: Register guarded nothing, and
NewWithRegistry was removed in #97 when the engine started taking compilers
instead of a registry. The live boundaries are Registry.Register,
engine.NewWith and irtest.WriteGolden, and a panic escaping a package is a
worse defect than the missing assertion the issue describes.

What changed:

  • Registry.Register rejects a nil compiler before it calls anything on it —
    both an untyped nil interface and a typed nil pointer stored in one, since
    screening only the first leaves half the hole open. The existing no-formats and
    duplicate-format errors are unchanged.
  • Registry's zero value is now a usable empty registry. A Registry written as
    a struct literal has a nil map, and registering into one panicked with
    "assignment to entry in nil map"; the map is allocated on first use instead.
  • engine.NewWith names the argument position in the error it wraps, so a caller
    passing several compilers can tell which one was rejected. It keeps delegating
    the preconditions themselves to Register rather than restating them.
  • irtest.WriteGolden refuses an empty path and a nil document, and
    CompareGolden refuses the same two by failing the test. A nil document
    marshals to the four bytes null, so an unguarded WriteGolden left a golden
    on disk that every later nil document matched: a snapshot that asserts nothing
    and looks exactly like a passing one.

Test plan

  • TestRegistry_RejectsNilCompiler covers both spellings of nil; each subtest
    panicked at compilers.go:58 before the guard.
  • TestRegistry_ZeroValueRegisters registers into a zero-value Registry; it
    panicked with "assignment to entry in nil map" before.
  • TestNewWith_NilCompiler passes the nil second, so the reported index proves
    it is the argument's own position rather than a constant; it segfaulted before.
    TestNewWith_RegisterError now pins that index too.
  • TestWriteGolden_RejectsBadInput asserts both errors and that a refused write
    leaves no file behind; the nil case previously wrote null and returned nil.
  • TestCompareGolden_RejectsBadInput compares a nil document against a golden
    containing null — the file an unguarded WriteGolden produces. Without the
    guard that comparison reports a clean match.
  • Each guard was reverted individually and the matching test confirmed red before
    being restored. Full gate green: gofmt, vet, golangci-lint, build, and the 100%
    coverage gate.

Closes#89

@OmarAlJarrah
OmarAlJarrah merged commit 8fafafd into mainAug 9, 2026
1 check passed
@OmarAlJarrah
OmarAlJarrah deleted the fix/engine-irtest-boundary-assertions branch August 9, 2026 09:46
Sign up for freeto 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.

engine+irtest: add the missing boundary assertions to NewWithRegistry and WriteGolden

1 participant

@OmarAlJarrah