Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lost in iteration: values lost when iterating ref head rules mixing static and dynamic paths #6926

Closed
anderseknert opened this issue Aug 13, 2024 · 2 comments · Fixed by #6957

Comments

@anderseknert
Copy link
Member

I encountered this issue when working on Regal (see issue for more details) earlier this summer, but since I was never able to reproduce it in OPA I figured it must be some special circumstance related to that project. Having now spent more time than I'd like to admit trying to narrow it down, I've finally been able to isolate the issue and reproduce it on OPA.

A nonsensical example, but it demonstrates the bug in the most compact form I could come up with. When mixing static and dynamic paths in a ref head rule, one type of iteration over the values can cause further iteration to not see all values.

package p

import rego.v1

obj.sub[x][x] contains x if some x in ["one", "two"]

obj[x][x] contains x if x := "whatever"

main contains x if {
    #[1 | obj.sub[_].one[_]]
    x := obj.sub[_][_][_]
}

At this point, evaluating main produces the expected result:

opa eval -f pretty -d policy.rego data.p.main
[
  "one",
  "two"
]

Uncommenting the first line in the main rule (iteration wrapped in a comprehension which shouldn't matter) however changes the result of evaluation:

opa eval -f pretty -d policy.rego data.p.main
[
  "one"
]

It seems that just the fact that we did obj.sub[_].one[_] once got the evaluator into a state where traversing the full object no longer returns all values.

@johanfylling
Copy link
Contributor

After a bit of investigating, I can confirm this is a virtual-cache issue. There are certain scenarios where the ref of a rule node is unified before the associated rules are evaluated, causing ref variables to be pre-defined, but the result is stored in the virtual cache under a key that ends "left" of all relevant ref components.
E.g. the ref to p.obj.sub[_].one[_] has the 2nd ref var unified to "one", which scopes eval of the rule(s); but the result is stored under the key p.obj.sub.

johanfylling added a commit to johanfylling/opa that referenced this issue Aug 23, 2024
…val ref unification

Fixes: open-policy-agent#6926
Signed-off-by: Johan Fylling <johan.dev@fylling.se>
@anderseknert
Copy link
Member Author

Great work on this @johanfylling! 👏

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

Successfully merging a pull request may close this issue.

2 participants