Skip to content

Commit

Permalink
topdown: Fix for empty documents generated by partial rules
Browse files Browse the repository at this point in the history
This commit fixes an issue in partial eval whereby OPA would generate
an incorrect expression referring to a non-existent/undefined virtual
document. This would occur if an expression referenced the full extent
of a virtual document generated by partial rules and those partial
rules were all undefined. In that case, the reference needs to be
unified with the default (empty) value for that virtual document.

Fixes #2492

Signed-off-by: Torin Sandall <torinsandall@gmail.com>
  • Loading branch information
tsandall committed Jul 6, 2020
1 parent fa5e302 commit 16743fe
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 4 deletions.
20 changes: 16 additions & 4 deletions topdown/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -1976,27 +1976,39 @@ func (e evalVirtualPartial) partialEvalSupport(iter unifyIterator) error {

path, term := e.e.savePackagePathAndTerm(e.plugged[:e.pos+1], e.ref)

if !e.e.saveSupport.Exists(path) {
var defined bool

if e.e.saveSupport.Exists(path) {
defined = true
} else {
for i := range e.ir.Rules {
err := e.partialEvalSupportRule(iter, e.ir.Rules[i], path)
ok, err := e.partialEvalSupportRule(iter, e.ir.Rules[i], path)
if err != nil {
return err
} else if ok {
defined = true
}
}
}

if !defined {
term = e.empty
}

return e.e.saveUnify(term, e.rterm, e.bindings, e.rbindings, iter)
}

func (e evalVirtualPartial) partialEvalSupportRule(iter unifyIterator, rule *ast.Rule, path ast.Ref) error {
func (e evalVirtualPartial) partialEvalSupportRule(iter unifyIterator, rule *ast.Rule, path ast.Ref) (bool, error) {

child := e.e.child(rule.Body)
child.traceEnter(rule)

e.e.saveStack.PushQuery(nil)
var defined bool

err := child.eval(func(child *eval) error {
child.traceExit(rule)
defined = true

current := e.e.saveStack.PopQuery()
plugged := current.Plug(e.e.caller.bindings)
Expand Down Expand Up @@ -2031,7 +2043,7 @@ func (e evalVirtualPartial) partialEvalSupportRule(iter unifyIterator, rule *ast
return nil
})
e.e.saveStack.PopQuery()
return err
return defined, err
}

func (e evalVirtualPartial) evalTerm(iter unifyIterator, term *ast.Term, termbindings *bindings) error {
Expand Down
10 changes: 10 additions & 0 deletions topdown/topdown_partial_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,16 @@ func TestTopDownPartialEval(t *testing.T) {
p[x2] = y2 { x2 = input.x; y2 = input.y }
`},
},
{
note: "automatic shallow inlining: full extent: no solutions",
query: "data.test.p = x",
modules: []string{
`package test
p[1] { input = 1; false }`,
},
wantQueries: []string{`x = set()`},
},
{
note: "automatic shallow inlining: full extent: iteration",
query: "data.test[x] = y",
Expand Down

0 comments on commit 16743fe

Please sign in to comment.