cue icon indicating copy to clipboard operation
cue copied to clipboard

BUG: Segmentation fault in cuelang.org/go/internal/core/adt.(*OpContext).freeNodeContext

Open s-7777 opened this issue 3 months ago • 0 comments

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

s-7777 avatar Sep 22 '25 09:09 s-7777