Skip to content

Commit

Permalink
topdown/copypropagation: only update call bindings when output is cap…
Browse files Browse the repository at this point in the history
…tured

updateBindings before checked if the last operand was a variable, and attempted to
replace it if it was. With `neq(s & set(), s)`, the last operand was a variable,
but not the output variable -- the output wasn't captured.

So now, we use the arity of the called function to determine if we can replace a
call.

Fixes open-policy-agent#3071.

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
  • Loading branch information
srenatus authored and jgchn committed Aug 20, 2021
1 parent 43400ee commit b70a4e5
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 4 deletions.
10 changes: 6 additions & 4 deletions topdown/copypropagation/copypropagation.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,12 @@ func (p *CopyPropagator) updateBindings(pctx *plugContext, expr *ast.Expr) bool
}
} else if expr.IsCall() {
terms := expr.Terms.([]*ast.Term)
output := terms[len(terms)-1]
if k, ok := output.Value.(ast.Var); ok && !p.livevars.Contains(k) && !pctx.headvars.Contains(k) {
pctx.removedEqs.Put(k, ast.CallTerm(terms[:len(terms)-1]...).Value)
return false
if p.compiler.GetArity(expr.Operator()) == len(terms)-2 { // with captured output
output := terms[len(terms)-1]
if k, ok := output.Value.(ast.Var); ok && !p.livevars.Contains(k) && !pctx.headvars.Contains(k) {
pctx.removedEqs.Put(k, ast.CallTerm(terms[:len(terms)-1]...).Value)
return false
}
}
}
return !isNoop(expr)
Expand Down
15 changes: 15 additions & 0 deletions topdown/topdown_partial_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2723,6 +2723,21 @@ func TestTopDownPartialEval(t *testing.T) {
},
wantQueries: []string{`x_term_1_01; x_term_1_01 = input[x_term_1_01]`},
},
{
note: "copypropagation: circular reference (bug 3071)",
query: "data.test.p",
modules: []string{`package test
p[y] {
s := { i | input[i] }
s & set() != s
y := sprintf("%v", [s])
}`,
},
wantQueries: []string{`data.partial.test.p`},
wantSupport: []string{`package partial.test
p[__local1__1] { __local0__1 = {i1 | input[i1]}; neq(and(__local0__1, set()), __local0__1); sprintf("%v", [__local0__1], __local1__1) }
`},
},
}

ctx := context.Background()
Expand Down

0 comments on commit b70a4e5

Please sign in to comment.