Files
releases/v1
Stephan Renatus bfd0d00073 ast: fix AnnotationSet memory leak via runtime.AddCleanup cycle
AnnotationSet.MergedLabels was introduced in v1.17.0 to cache merged
label maps per rule. It used weak.Pointer[Rule] as the cache key and
registered a runtime.AddCleanup to evict the entry when the rule was
garbage-collected.

The cleanup closure captured `as` (the AnnotationSet pointer). The
AnnotationSet holds strong references to every module it was built
from (as.modules), and each module holds its rules. This meant that
once any rule had a cleanup registered:

  runtime cleanup queue → closure → AnnotationSet → modules → Rule

Rule was always reachable through that path, so the cleanup could
never fire. Nothing would ever delete the closure, so the
AnnotationSet and all of its rules were permanently retained.

In practice, OPA's dynamic bundle plugin recompiles policies on every
poll cycle. Each compilation creates a fresh AnnotationSet. With the
bug, old AnnotationSets accumulated in the heap indefinitely, causing
the OOM-kill pattern reported in #8817.

Fix: drop the cache entirely. MergedLabels now calls Chain and
mergeChainLabels on every invocation. Chain is a handful of map
lookups and MergedLabels is called at most once per evaluated rule per
request, so the recomputation cost is negligible. This removes the
mergedLabels sync.Map field, the ruleLabelsEntry type, and the
runtime/sync/weak imports.

A regression test uses weak.Pointer[AnnotationSet] to assert that an
AnnotationSet is collectable after it goes out of scope.

Fixes #8817
Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
2026-06-29 12:42:21 +02:00
..
2025-10-10 17:51:02 +02:00
2026-03-06 22:07:35 +00:00
2026-05-13 13:11:27 +02:00
2024-12-12 15:27:34 +01:00