Skip to content

openapi: a single null branch lowers to a union with no variants #416

Description

@OmarAlJarrah

Problem

An anyOf whose only branch is {"type": "null"} lowers to a Union type node that declares no
variants at all. irverify rejects the result, so the compiler produces a document its own
invariant checker calls invalid, and morphic compile still exits 0.

Minimal spec:

{"components":{"schemas":{"Fuzzed":{"anyOf":[{"type":"null"}]}}},
 "info":{"title":"FuzzSchema","version":"1.0.0"},"openapi":"3.1.0","paths":{}}

The type it produces has no variants key:

$ go run ./cmd/morphic compile spec.json | jq -c '.types["t/openapi/components/schemas/Fuzzed"]'
{"kind":"union","id":"t/openapi/components/schemas/Fuzzed","name":{"source":"Fuzzed","canonical":"fuzzed"},
 "anonymous":false,"docs":{},"sensitive":false,
 "provenance":{"source":0,"pointer":"/components/schemas/Fuzzed"},"exclusive":false,"wireTagged":false}

and the harness reports it:

$ go run ./cmd/morphic-harness spec.json
spec.json violations [{Code:ir/union-no-variants Message:union declares no variants, so no value
inhabits it Path:types[t/openapi/components/schemas/Fuzzed]}]
exit status 1

Both reproduce at 29801f7 on main.

The {X, null} collapse presumably drops the null branch as a nullability marker; with nothing
beside it there is no branch left, and nothing notices that the union is then empty. Either the
schema should not become a union at all, or the collapse must refuse to empty one.

How it surfaced

go test ./... is green — no committed seed reaches it. A bounded -fuzz search of
FuzzLowerSchema finds it in 1.45 s from a cleared corpus (go clean -fuzzcache, no committed
reproducer), minimizing to {"anyOf":[{"type":"null"}]}. That means any CI step that fuzzes this
target reddens on essentially every run until this is fixed.

Acceptance

  • The spec above either lowers to something other than an empty union, or raises a diagnostic.
  • go run ./cmd/morphic-harness on it reports no violation.
  • A conformance or golden case pins whichever behaviour is chosen, declared in the order that was
    wrong if the fix is order-sensitive.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    type:bugDefect in shipped behavior

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions