cue
cue copied to clipboard
BUG: Segmentation fault in cuelang.org/go/internal/core/adt.(*OpContext).freeNodeContext
What version of CUE are you using (cue version)?
cue version v0.14.1
go version go1.24.6
-buildmode exe
-compiler gc
-trimpath true
DefaultGODEBUG gotestjsonbuildtext=1,multipathtcp=0,randseednop=0,rsa1024min=0,tlsmlkem=0,x509rsacrt=0,x509usepolicies=0
CGO_ENABLED 1
GOARCH arm64
GOOS darwin
GOARM64 v8.0
cue.lang.version v0.14.1
### Does this issue reproduce with the latest stable release?
What did you do?
// BUG: Segmentation fault in cuelang.org/go/internal/core/adt.(*OpContext).freeNodeContext
//
// This reproduces a memory management bug when CUE evaluates a specific pattern of:
// 1. Complex nested field traversal with multiple conditional branches
// 2. Self-referential validation within for loops
// 3. Multiple instantiations of complex definitions
//
// The crash occurs during memory reclamation when CUE tries to free node contexts
// that have circular dependencies created by the self-referential pattern below.
package t
import "strings"
import "list"
// MINIMAL ENTITY STRUCTURE
// We're modeling a parent-child relationship graph.
// In our real system, this represents hierarchical data relationships.
// The crash requires at least 2 entities with cyclic relationships (a->b->a).
#E: {
a: {n:"a", p:{ap:{b:"b"}}} // entity 'a' has parent 'b'
b: {n:"b", p:{ap:{a:"a"}}} // entity 'b' has parent 'a' (creates cycle)
}
// PATH RESOLUTION DEFINITION
// This traverses the parent hierarchy to find paths between entities.
// simplifying this prevents the crash.
#R: {
s: string // start entity
t: string // target path like "entity.field"
// Parse the target to extract entity type
let ps = strings.Split(t, ".")
let ty = ps[0]
let ip = !list.Contains(["i"], ty)
// NESTED CONDITIONAL TRAVERSAL - This complexity is required for crash
// The multiple if statements with nested for loops create deep evaluation trees
let _p = {
// Direct match
if s == ty { p: "" }
// Single-level parent traversal
if s != ty && #E[s].p.ap != _|_ {
for p, _ in #E[s].p.ap {
if p == ty { p: "p" }
}
}
// CRITICAL: Two-level nested traversal
// This nested for loop within conditionals is essential for the crash
if s != ty && #E[s].p.ap != _|_ {
for p1, _ in #E[s].p.ap {
if #E[p1].p.ap != _|_ {
for p2, _ in #E[p1].p.ap {
if p2 == ty { p: "p.p" }
}
}
}
}
}
// MULTIPLE LET BINDINGS - These contribute to memory pressure
// Removing these let bindings often prevents the crash
if ip && _p.p != _|_ {
r: {
let _e = #E[ty]
let _f = strings.Join(ps[1:], ".")
e:_e, f:_f, p:_p.p, t:"s"
}
}
}
// VALIDATION WITH SELF-REFERENCE
// This is where we use the path resolution in a self-referential way.
// In our real system, this validates that input paths can be resolved.
v: {
i: {x:"a.d", y:"a.e"} // input paths to validate
// We think
// The crash happens because this creates circular dependencies:
// 1. For each input, we instantiate #R (complex definition)
// 2. We then reference v.val[...] WITHIN the same structure being built
// 3. This self-reference combined with #R's complexity overwhelms memory management
val: {
for pm, vl in i {
if (vl & string) != _|_ {
"\(pm)_p": #R & {s:"b", t:vl}
// Culprit?
"\(pm)_v": (v.val["\(pm)_p"].r != _|_)
}
}
}
// Second for loop that processes validation results
// This additional iteration over the same structure adds to the problem
av: true
for f, r in val {
if strings.HasSuffix(f, "_v") {
if r == false { av: false }
}
}
}
What did you expect to see?
Cue eval/vet etc succeed.
What did you see instead?
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x0 pc=0x1009910dc]
goroutine 1 [running]:
cuelang.org/go/internal/core/adt.runTask.func1()
cuelang.org/go/internal/core/adt/sched.go:688 +0xc0
panic({0x101088100?, 0x10181cc30?})
runtime/panic.go:792 +0x124
cuelang.org/go/internal/core/adt.runTask.func1()
cuelang.org/go/internal/core/adt/sched.go:688 +0xc0
panic({0x101088100?, 0x10181cc30?})
runtime/panic.go:792 +0x124
cuelang.org/go/internal/core/adt.(*OpContext).freeNodeContext(...)
cuelang.org/go/internal/core/adt/eval.go:1493
cuelang.org/go/internal/core/adt.reclaimer.reclaim({0x14000258848?, 0x8?, 0x8e?, 0x5d?}, 0x1400034bc20)
cuelang.org/go/internal/core/adt/mem.go:168 +0x13c
cuelang.org/go/internal/core/adt.reclaimer.reclaim({0x14000258848?, 0x38?, 0xed?, 0x99?}, 0x1400034bb80)
cuelang.org/go/internal/core/adt/mem.go:187 +0x284
cuelang.org/go/internal/core/adt.(*OpContext).reclaimRecursive(...)
cuelang.org/go/internal/core/adt/mem.go:104
cuelang.org/go/internal/core/adt.reclaimer.reclaim({0x14000258848?, 0x4?, 0x38?, 0x82?}, 0x1400034a960)
cuelang.org/go/internal/core/adt/mem.go:145 +0x7c
cuelang.org/go/internal/core/adt.(*OpContext).reclaimTempBuffers(0x14000258848, 0x1400034a960)
cuelang.org/go/internal/core/adt/mem.go:115 +0x3c
cuelang.org/go/internal/core/adt.(*Vertex).unify.func1()
cuelang.org/go/internal/core/adt/unify.go:173 +0x50
cuelang.org/go/internal/core/adt.(*Vertex).unify(0x1400034a960, 0x14000258848, 0x7fff, 0x4, 0x1)
cuelang.org/go/internal/core/adt/unify.go:492 +0xc6c
cuelang.org/go/internal/core/adt.(*nodeContext).completeAllArcs(0x1400034db88, 0x7fff, 0x4, 0x1)
cuelang.org/go/internal/core/adt/unify.go:607 +0xf4
cuelang.org/go/internal/core/adt.(*Vertex).unify(0x1400034a500, 0x14000258848, 0x7fff, 0x4, 0x1)
cuelang.org/go/internal/core/adt/unify.go:329 +0x98c
cuelang.org/go/internal/core/adt.(*OpContext).unify(0x101000001?, 0x14000327ec0?, {0xb8?, 0x36?, 0x40?})
cuelang.org/go/internal/core/adt/eval.go:160 +0x16c
cuelang.org/go/internal/core/adt.(*Vertex).Finalize(0x1011c8480?, 0x14000258848)
cuelang.org/go/internal/core/adt/composite.go:1065 +0x5c
cuelang.org/go/internal/core/adt.(*OpContext).validate(0x14000258848, 0x1400030f9e0, {0x1011c74d0, 0x140002ed810}, {0x1011c4380, 0x140002b5aa0}, 0xb, {0x0?, 0x0?, 0x0?})
cuelang.org/go/internal/core/adt/expr.go:1528 +0x4c8
cuelang.org/go/internal/core/adt.(*BinaryExpr).evaluate(0x140002fd020, 0x14000258848, {0x0?, 0x0?, 0x0?})
cuelang.org/go/internal/core/adt/expr.go:1420 +0x198
cuelang.org/go/internal/core/adt.(*OpContext).evalStateCI(0x14000258848, {0x1011c4640, 0x140002fd020}, {0x90?, 0x183?, 0x1?})
cuelang.org/go/internal/core/adt/context.go:735 +0x38c
cuelang.org/go/internal/core/adt.processExpr(0x14000258848?, 0x1400033f710, 0x2?)
cuelang.org/go/internal/core/adt/tasks.go:91 +0xb0
cuelang.org/go/internal/core/adt.runTask(0x1400033f710, 0x2)
cuelang.org/go/internal/core/adt/sched.go:710 +0x514
cuelang.org/go/internal/core/adt.(*scheduler).process(0x14000344898, 0x2, 0x2)
cuelang.org/go/internal/core/adt/sched.go:404 +0x1bc
cuelang.org/go/internal/core/adt.(*ForClause).yield(0x140002b5b60, 0x14000327140)
cuelang.org/go/internal/core/adt/expr.go:2280 +0x1bc
cuelang.org/go/internal/core/adt.(*OpContext).yield(0x14000258848, 0x140002a90e0, 0x1400030f7a0, 0x14000306180, {0xc0?, 0x34?, 0x40?}, 0x140002ff7f0)
cuelang.org/go/internal/core/adt/comprehension.go:331 +0x22c
cuelang.org/go/internal/core/adt.(*nodeContext).processComprehension(0x14000308008, 0x14000362ee0, 0x0)
cuelang.org/go/internal/core/adt/comprehension.go:435 +0xb8
cuelang.org/go/internal/core/adt.processComprehension(0x1400030f7a0?, 0x1400033eea0, 0xa0?)
cuelang.org/go/internal/core/adt/tasks.go:222 +0x94
cuelang.org/go/internal/core/adt.runTask(0x1400033eea0, 0x4)
cuelang.org/go/internal/core/adt/sched.go:710 +0x514
cuelang.org/go/internal/core/adt.(*scheduler).process(0x14000308218, 0x7f7f, 0x4)
cuelang.org/go/internal/core/adt/sched.go:404 +0x1bc
cuelang.org/go/internal/core/adt.(*Vertex).unify(0x140002a90e0, 0x14000258848, 0x7fff, 0x4, 0x1)
cuelang.org/go/internal/core/adt/unify.go:243 +0x450
cuelang.org/go/internal/core/adt.(*nodeContext).completeAllArcs(0x14000224c08, 0x7fff, 0x4, 0x1)
cuelang.org/go/internal/core/adt/unify.go:607 +0xf4
cuelang.org/go/internal/core/adt.(*Vertex).unify(0x140002a8f00, 0x14000258848, 0x7fff, 0x4, 0x1)
cuelang.org/go/internal/core/adt/unify.go:329 +0x98c
cuelang.org/go/internal/core/adt.(*OpContext).unify(0x1?, 0x0?, {0x88?, 0x2d?, 0x40?})
cuelang.org/go/internal/core/adt/eval.go:160 +0x16c
cuelang.org/go/internal/core/adt.(*Vertex).Finalize(0x140002d7cc8?, 0x14000258848)
cuelang.org/go/internal/core/adt/composite.go:1065 +0x5c
cuelang.org/go/cue.newVertexRoot(0x1400026dc00, 0x0?, 0x140002a8f00)
cuelang.org/go/cue/types.go:607 +0x2c
cuelang.org/go/cue.newValueRoot(0x0?, 0x140002d7df0?, {0x1011c44c0?, 0x140002a8f00?})
cuelang.org/go/cue/types.go:616 +0x40
cuelang.org/go/cue.(*Context).make(0x1400026dc00, 0x140002a8f00)
cuelang.org/go/cue/context.go:256 +0x84
cuelang.org/go/cue.(*Context).BuildInstances(0x1400026dc00, {0x140003640d8, 0x1, 0x1019ebef0?})
cuelang.org/go/cue/context.go:154 +0x1ac
cuelang.org/go/cmd/cue/cmd.buildInstances(0x14000278b40, {0x140003640d8, 0x1, 0x140002c2000?}, 0x1)
cuelang.org/go/cmd/cue/cmd/common.go:704 +0x34
cuelang.org/go/cmd/cue/cmd.parseArgs(0x14000278b40, {0x14000049670, 0x1, 0x1}, 0x1400026ed70)
cuelang.org/go/cmd/cue/cmd/common.go:581 +0x9d4
cuelang.org/go/cmd/cue/cmd.runDef(0x14000278b40, {0x14000049670, 0x1, 0x1})
cuelang.org/go/cmd/cue/cmd/def.go:55 +0x64
cuelang.org/go/cmd/cue/cmd.newDefCmd.mkRunE.func1(0x140001c2e00?, {0x14000049670, 0x1, 0x1})
cuelang.org/go/cmd/cue/cmd/root.go:154 +0x27c
github.com/spf13/cobra.(*Command).execute(0x1400028af08, {0x14000049630, 0x1, 0x1})
github.com/spf13/[email protected]/command.go:1015 +0x844
github.com/spf13/cobra.(*Command).ExecuteC(0x1400028a008)
github.com/spf13/[email protected]/command.go:1148 +0x384
github.com/spf13/cobra.(*Command).Execute(...)
github.com/spf13/[email protected]/command.go:1071
github.com/spf13/cobra.(*Command).ExecuteContext(...)
github.com/spf13/[email protected]/command.go:1064
cuelang.org/go/cmd/cue/cmd.(*Command).Run(0x14000278b40, {0x1011c2198?, 0x14000279a10?})
cuelang.org/go/cmd/cue/cmd/root.go:406 +0x58
cuelang.org/go/cmd/cue/cmd.Main()
cuelang.org/go/cmd/cue/cmd/root.go:305 +0x118
main.main()
cuelang.org/go/cmd/cue/main.go:24 +0x1c