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

ast: forbid dynamic recursion with hidden document #3876

Conversation

srenatus
Copy link
Contributor

@srenatus srenatus commented Oct 8, 2021

Before, this package would slip through:

package system.main

allow {
	data[input]
}

and wreck havoc either in evaluation (topdown) or the wasm compilation.

Now, it'll be caught:

open-policy-agent/opa % opa eval -fpretty -d r.rego 'data.system.main'
1 error occurred: r.rego:3: rego_recursion_error: rule allow is recursive: allow -> allow

Also includes

  • two minor changes to the ast compile package (pre-allocating a slice, replacing one panic with another); and
  • re-orders some bits in the rego package to avoid extra work for wasm when wasm isn't available.

@srenatus srenatus force-pushed the sr/ast/dynamic-recursion-with-hidden-document branch from e1efa89 to 6eb5fb9 Compare October 8, 2021 10:12
ast/compile.go Outdated
@@ -591,9 +591,6 @@ func (c *Compiler) GetRulesDynamic(ref Ref) (rules []*Rule) {
// This part of the ref is a dynamic term. We can't know what it refers
// to and will just need to try all of the children.
for _, child := range node.Children {
if child.Hide {
continue
}
insertRules(set, child.Values)
walk(child, i+1)
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was a bit hesitant changing GetRulesDynamic, but I think the graph that's built with it isn't used in other places. Tests seem to agree.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hrmmm, I agree that this is probably safe and unlikely to break anyone... on the other hand, we could extend the compiler with another function that accepts an option to skip (or include) hidden nodes in the result; then the compiler can be modified to use that new function while building the graph and the GetRulesDynamic function doesn't have to change--there's also the GetRulesWithPrefix function (which appears unused) that also checks the 'hide' bit on the nodes.

GetRulesDynamic could be updated to call the new function and deprecated. Just my 2c.

@srenatus srenatus marked this pull request as ready for review October 8, 2021 10:24
Copy link
Member

@tsandall tsandall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a thought about backwards compatibility.

ast/compile.go Outdated
@@ -591,9 +591,6 @@ func (c *Compiler) GetRulesDynamic(ref Ref) (rules []*Rule) {
// This part of the ref is a dynamic term. We can't know what it refers
// to and will just need to try all of the children.
for _, child := range node.Children {
if child.Hide {
continue
}
insertRules(set, child.Values)
walk(child, i+1)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hrmmm, I agree that this is probably safe and unlikely to break anyone... on the other hand, we could extend the compiler with another function that accepts an option to skip (or include) hidden nodes in the result; then the compiler can be modified to use that new function while building the graph and the GetRulesDynamic function doesn't have to change--there's also the GetRulesWithPrefix function (which appears unused) that also checks the 'hide' bit on the nodes.

GetRulesDynamic could be updated to call the new function and deprecated. Just my 2c.

@srenatus srenatus force-pushed the sr/ast/dynamic-recursion-with-hidden-document branch from 6eb5fb9 to f855040 Compare October 13, 2021 08:34
Before, this package would slip through:

    package system.main

    allow {
    	data[input]
    }

and wreck havoc either in evaluation (topdown) or the wasm compilation.

Now, it'll be caught:

    open-policy-agent/opa % opa eval -fpretty -d r.rego 'data.system.main'
    1 error occurred: r.rego:3: rego_recursion_error: rule allow is recursive: allow -> allow

Signed-off-by: Stephan Renatus <[email protected]>
@srenatus srenatus force-pushed the sr/ast/dynamic-recursion-with-hidden-document branch from f855040 to 9c7de2f Compare October 13, 2021 08:35
@srenatus srenatus force-pushed the sr/ast/dynamic-recursion-with-hidden-document branch from 9c7de2f to bfbb7e5 Compare October 13, 2021 08:47
@@ -347,7 +347,7 @@ func saveRequired(c *ast.Compiler, ic *inliningControl, icIgnoreInternal bool, s
} else if ic.Disabled(v.ConstantPrefix(), icIgnoreInternal) {
found = true
} else {
for _, rule := range c.GetRulesDynamic(v) {
for _, rule := range c.GetRulesDynamicWithOpts(v, ast.RulesOptions{IncludeHiddenModules: false}) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👀 This is for backwards-compatibility with how this worked before. I wonder if we really don't want system modules here, though; if they would ever come in play with this....

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good question--we probably do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't want to touch that without a test case, but I also seriously want this merged 😅

I'll check this in a follow-up!

@srenatus srenatus merged commit 9e4ddd1 into open-policy-agent:main Oct 26, 2021
@srenatus srenatus deleted the sr/ast/dynamic-recursion-with-hidden-document branch October 26, 2021 14:12
dolevf pushed a commit to dolevf/opa that referenced this pull request Nov 4, 2021
…#3876)

* rego/PrepareForEval: don't compile wasm if there's no engine

* ast/compile: include hidden nodes in recursion check

Before, this package would slip through:

    package system.main

    allow {
    	data[input]
    }

and wreck havoc either in evaluation (topdown) or the wasm compilation.

Now, it'll be caught:

    open-policy-agent/opa % opa eval -fpretty -d r.rego 'data.system.main'
    1 error occurred: r.rego:3: rego_recursion_error: rule allow is recursive: allow -> allow

Signed-off-by: Stephan Renatus <[email protected]>
Signed-off-by: Dolev Farhi <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants