Skip to content

Harden jsonlit and reject unsupported syntax at Compile time#15

Merged
myzie merged 1 commit into
mainfrom
jsonlit-fixes-and-compile-validator
May 8, 2026
Merged

Harden jsonlit and reject unsupported syntax at Compile time#15
myzie merged 1 commit into
mainfrom
jsonlit-fixes-and-compile-validator

Conversation

@myzie
Copy link
Copy Markdown
Contributor

@myzie myzie commented May 8, 2026

Summary

Two related improvements to the front-end of expr:

jsonlit edge cases. The token-based JSON-style rewrite in internal/jsonlit had several shapes where valid Go input either failed to parse or was silently miscompiled. Fixed by making isArrayTypeFollow recursive (for [N][...]T), accepting <-/)/] as type-end tokens before { (for []<-chan T{}, func() {}, List[int]{}, []interface{}{1}), tracking a brace stack so nested type-omitted composites like [][]int{{1,2}} and []struct{X int}{{1}} are left alone while map[string]any{"k": {"j": 1}} still gets the inner brace rewritten, and splitting the empty-[] edit into two splices so comments are preserved. Adds an internal/jsonlit/README.md describing the approach, classification, and known limits.

Compile-time validation. Adds a one-pass AST validator (validate.go) invoked from Compile immediately after parsing. Forms expr does not evaluate (function literals, slice expressions, type assertions, channel/pointer/address ops, bitwise operators, imaginary literals, spread args, generic instantiations, fixed-size arrays, typed slices/maps other than []any / map[string]any) now fail at Compile with ErrCompile and a line:col prefix, instead of failing at Run with ErrEvaluate. Switches Compile to parser.ParseExprFrom for positioned errors. Runtime checks are kept as defense in depth.

Three existing tests previously asserting ErrEvaluate for unsupported syntax now expect ErrCompile. docs/reference/spec.md is updated accordingly.

Test plan

  • go test ./... passes
  • go test -fuzz=FuzzRewrite -fuzztime=30s ./internal/jsonlit/ clean (with new seeds for the previously broken shapes)
  • go test -fuzz=FuzzCompile -fuzztime=20s . clean (>1M execs)
  • go test -fuzz=FuzzEval -fuzztime=20s . clean (>400k execs)
  • New validate_test.go pins each unsupported form to ErrCompile plus three nested-rejection cases
  • internal/jsonlit/jsonlit_test.go adds explicit cases for every fixed shape

🤖 Generated with Claude Code

jsonlit:
- Fix `[N][...]T` array-type detection so `[2][]int{{1},{2}}` and
  `[3][4]int{{1,2,3,4}}` survive the rewrite (recursive
  `isArrayTypeFollow`).
- Accept `<-` as a slice-type prefix follow so `[]<-chan T{}` passes
  through.
- Treat `)`, `]`, and `}` as type-end tokens before `{` so
  `func() {}`, `List[int]{}`, and `[]interface{}{1}` are not mangled
  into bare object literals.
- Track a brace stack with three states (object, any-elemented typed,
  inert typed) so nested type-omitted composites like
  `[][]int{{1,2},{3,4}}` and `[]struct{X int}{{1},{2}}` are left
  alone, while `map[string]any{"k": {"j": 1}}` and `[]any{{"k": 1}}`
  still get the inner brace rewritten.
- Preserve comments inside empty `[]` by splitting the splice into
  two edits.
- Add an `internal/jsonlit/README.md` describing the approach,
  bracket and brace classification, and known limitations.
- Expand the test suite and fuzz seed corpus with the previously
  broken shapes.

Compile-time validator:
- Add `validate.go` that walks the parsed AST and rejects every
  unsupported form (function literals, slice expressions, type
  assertions, channel ops, pointer/address ops, bitwise operators,
  imaginary literals, spread args, generic instantiations, fixed-
  size arrays, and typed slices/maps other than `[]any` /
  `map[string]any`) with `ErrCompile` and a `line:col` prefix.
- Switch `Compile` to `parser.ParseExprFrom` with a local FileSet so
  validator errors carry positions like the parser's own.
- Update three existing tests that previously asserted
  `ErrEvaluate` for unsupported forms to now expect `ErrCompile`,
  and update `docs/reference/spec.md` accordingly.
- Keep the runtime checks as defense in depth.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@myzie myzie merged commit 388b4ce into main May 8, 2026
1 check passed
@myzie myzie deleted the jsonlit-fixes-and-compile-validator branch May 8, 2026 13:19
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