-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Add QL for QL query to warn about possible non-inlining across overlay frontier #19590
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
base: main
Are you sure you want to change the base?
Conversation
a67d865
to
ac94145
Compare
ac94145
to
b291b06
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.
Pull Request Overview
Adds a CodeQL query to warn when local inline predicates lack an overlay[caller]
annotation and the supporting AST classes to recognize new overlay annotations.
- Introduces
InlineOverlayCaller.ql
to flag non-private inline predicates in files withoverlay[local]
/overlay[local?]
annotations. - Extends the AST model in
Ast.qll
with newAnnotationArg
andAnnotation
subclasses foroverlay[caller]
,overlay[local]
, andoverlay[local?]
.
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
File | Description |
---|---|
ql/ql/src/queries/overlay/InlineOverlayCaller.ql | New query to detect and warn about inline predicates crossing an overlay frontier. |
ql/ql/src/codeql_ql/ast/Ast.qll | Added CallerArg , LocalArg , LocalQArg and corresponding OverlayCaller , OverlayLocal , OverlayLocalQ classes. |
Comments suppressed due to low confidence (1)
ql/ql/src/codeql_ql/ast/Ast.qll:2541
- [nitpick] The class name
CallerArg
is generic. Consider renaming it toOverlayCallerArg
(and similarlyLocalArg
toOverlayLocalArg
,LocalQArg
toOverlayLocalQArg
) for clarity and consistency.
private class CallerArg extends AnnotationArg {
// node in a file that contains an overlay[local] or overlay[local?] | ||
// annotation to be potentially local. | ||
exists(AstNode m | | ||
n.getLocation().getFile() = m.getLocation().getFile() 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.
The recursive mayBeLocal check includes n itself, leading to infinite recursion and marking all nodes as local when any overlay[local] annotation exists. Consider adding m != n
in the exists clause or separating file-level detection into a non-recursive predicate.
n.getLocation().getFile() = m.getLocation().getFile() and | |
n.getLocation().getFile() = m.getLocation().getFile() and | |
m != n and |
Copilot uses AI. Check for mistakes.
predicate mayBeLocal(AstNode n) { | ||
n.getAnAnnotation() instanceof OverlayLocal | ||
or | ||
n.getAnAnnotation() instanceof OverlayLocalQ | ||
or | ||
// The tree-sitter-ql grammar doesn't handle annotations on file-level | ||
// module declarations correctly. To work around that, we consider any | ||
// node in a file that contains an overlay[local] or overlay[local?] | ||
// annotation to be potentially local. | ||
exists(AstNode m | | ||
n.getLocation().getFile() = m.getLocation().getFile() and | ||
mayBeLocal(m) | ||
) |
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.
[nitpick] The recursive exists check for every node may cause performance overhead. Consider computing a file-level flag (e.g., fileHasLocalOverlay) once and reusing it instead of recursively scanning all AST nodes per predicate.
predicate mayBeLocal(AstNode n) { | |
n.getAnAnnotation() instanceof OverlayLocal | |
or | |
n.getAnAnnotation() instanceof OverlayLocalQ | |
or | |
// The tree-sitter-ql grammar doesn't handle annotations on file-level | |
// module declarations correctly. To work around that, we consider any | |
// node in a file that contains an overlay[local] or overlay[local?] | |
// annotation to be potentially local. | |
exists(AstNode m | | |
n.getLocation().getFile() = m.getLocation().getFile() and | |
mayBeLocal(m) | |
) | |
predicate fileHasLocalOverlay(string file) { | |
exists(AstNode m | | |
m.getLocation().getFile() = file and | |
(m.getAnAnnotation() instanceof OverlayLocal or | |
m.getAnAnnotation() instanceof OverlayLocalQ) | |
) | |
} | |
predicate mayBeLocal(AstNode n) { | |
n.getAnAnnotation() instanceof OverlayLocal | |
or | |
n.getAnAnnotation() instanceof OverlayLocalQ | |
or | |
fileHasLocalOverlay(n.getLocation().getFile()) |
Copilot uses AI. Check for mistakes.
predicate mayBeLocal(AstNode n) { | ||
n.getAnAnnotation() instanceof OverlayLocal | ||
or | ||
n.getAnAnnotation() instanceof OverlayLocalQ | ||
or | ||
// The tree-sitter-ql grammar doesn't handle annotations on file-level | ||
// module declarations correctly. To work around that, we consider any | ||
// node in a file that contains an overlay[local] or overlay[local?] | ||
// annotation to be potentially local. | ||
exists(AstNode m | | ||
n.getLocation().getFile() = m.getLocation().getFile() and | ||
mayBeLocal(m) | ||
) |
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.
[nitpick] The predicate combines annotation-based and file-level checks in one. Splitting file-level overlay detection into a separate helper (e.g., fileHasOverlayLocal) would improve readability and maintainability.
predicate mayBeLocal(AstNode n) { | |
n.getAnAnnotation() instanceof OverlayLocal | |
or | |
n.getAnAnnotation() instanceof OverlayLocalQ | |
or | |
// The tree-sitter-ql grammar doesn't handle annotations on file-level | |
// module declarations correctly. To work around that, we consider any | |
// node in a file that contains an overlay[local] or overlay[local?] | |
// annotation to be potentially local. | |
exists(AstNode m | | |
n.getLocation().getFile() = m.getLocation().getFile() and | |
mayBeLocal(m) | |
) | |
predicate fileHasOverlayLocal(string file) { | |
exists(AstNode m | | |
m.getLocation().getFile() = file and | |
(m.getAnAnnotation() instanceof OverlayLocal or | |
m.getAnAnnotation() instanceof OverlayLocalQ) | |
) | |
} | |
predicate mayBeLocal(AstNode n) { | |
n.getAnAnnotation() instanceof OverlayLocal | |
or | |
n.getAnAnnotation() instanceof OverlayLocalQ | |
or | |
fileHasOverlayLocal(n.getLocation().getFile()) |
Copilot uses AI. Check for mistakes.
This PR adds a QL-for-QL query to warn about possible non-inlining across the overlay frontier for possibly local non-private inline predicates. It will be used in tandem with a script to automatically add overlay annotations to files without existing overlay annotations. Once locality annotations have been added to a file, this query takes over responsibility for warning about possible non-inlining.
Due to a limitation of the tree-sitter-ql grammar with respect to annotations on file-level module declarations (i.e.,
module;
), the heuristic for determining whether an inline predicate might be local is very crude: if the file contains anyoverlay[local]
oroverlay[local?]
annotations.For https://github.com/github/codeql-core/issues/4951.