-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Ruby: CFG: make all expressions "post-order" nodes #7394
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
Conversation
4388f19
to
fae3005
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't reviewed the test output, but the changes in ControlFlowGraphImpl.qll
all look sensible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, it even simplified some existing logic. I suggest we rebase this once #7393 has been merged, and then get rid of the last commit.
/** | ||
* All `Expr` nodes are `PostOrderTree`s | ||
*/ | ||
query predicate nonPostOrderExprTypes(string cls) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you consider
import codeql.ruby.controlflow.internal.Completion
import codeql.ruby.controlflow.internal.ControlFlowGraphImplShared
query predicate nonPostOrderExpr(Expr e, string cls) {
cls = e.getPrimaryQlClasses() and
not exists(e.getDesugared()) and
exists(AstNode last, Completion c |
last(e, last, c) and
last != e and
c instanceof NormalCompletion
)
}
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That gives quite a few results : https://github.com/github/codeql/runs/4549392461?check_suite_focus=true
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That made me realize that the modelling of InClause
is actually not like (I think) it should be. There is a subtle difference: before, the node for the InClause
itself was visited regardless of a match, but now it is only visited if there is a match.
There are two options: Revert 1343ed5 or use CFG splitting to make sure that InClauses
are truly post-order. I don't think splitting is worth the effort, so I suggest a revert.
With a revert, we can update the check above to
query predicate nonPostOrderExpr(Expr e, string cls) {
cls = e.getPrimaryQlClasses() and
not exists(e.getDesugared()) and
not e instanceof InClause and
not e instanceof BeginExpr and
not e instanceof Namespace and
not e instanceof Toplevel and
exists(AstNode last, Completion c |
last(e, last, c) and
last != e and
c instanceof NormalCompletion
)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That made me realize that the modelling of
InClause
is actually not like (I think) it should be. There is a subtle difference: before, the node for theInClause
itself was visited regardless of a match, but now it is only visited if there is a match.
I think this is the correct behaviour; if there is no match then the InClause
has no value (not even nil
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed, perhaps InClause
shouldn't be an Expr
in the first place.
ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
Outdated
Show resolved
Hide resolved
| | ||
next = this.getCondition() | ||
last(this.getPattern(), pred, c) and | ||
not c.(MatchingCompletion).getValue() = false and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be c.(MatchingCompletion).getValue() = true
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A pattern may also end with a simple completion, for example a *var
never fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could write the following instead c instanceof MatchingCompletion implies c.(MatchingCompletion).getValue() = true
fae3005
to
b55aa36
Compare
This reverts commit 1343ed5.
8209748
to
46144fe
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I have started a final DCA run; let's wait for that before we merge.
This reverts commit cff63fa.
1dc8f4c
to
6960f54
Compare
6960f54
to
6c71148
Compare
No description provided.