Skip to content

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

kaspersv
Copy link
Contributor

@kaspersv kaspersv commented May 27, 2025

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 any overlay[local] or overlay[local?] annotations.

For https://github.com/github/codeql-core/issues/4951.

@kaspersv kaspersv force-pushed the kaspersv/overlay-inline-warning branch from a67d865 to ac94145 Compare May 28, 2025 12:17
@kaspersv kaspersv force-pushed the kaspersv/overlay-inline-warning branch from ac94145 to b291b06 Compare May 28, 2025 12:41
@kaspersv kaspersv marked this pull request as ready for review May 30, 2025 11:25
@Copilot Copilot AI review requested due to automatic review settings May 30, 2025 11:25
@kaspersv kaspersv requested a review from a team as a code owner May 30, 2025 11:25
Copy link
Contributor

@Copilot Copilot AI left a 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 with overlay[local]/overlay[local?] annotations.
  • Extends the AST model in Ast.qll with new AnnotationArg and Annotation subclasses for overlay[caller], overlay[local], and overlay[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 to OverlayCallerArg (and similarly LocalArg to OverlayLocalArg, LocalQArg to OverlayLocalQArg) 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
Copy link
Preview

Copilot AI May 30, 2025

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.

Suggested change
n.getLocation().getFile() = m.getLocation().getFile() and
n.getLocation().getFile() = m.getLocation().getFile() and
m != n and

Copilot uses AI. Check for mistakes.

Comment on lines +14 to +26
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)
)
Copy link
Preview

Copilot AI May 30, 2025

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.

Suggested change
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.

Comment on lines +14 to +26
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)
)
Copy link
Preview

Copilot AI May 30, 2025

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.

Suggested change
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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant