Ruby: add overlay[local] annotations to AST/CFG/SSA layers

This commit is contained in:
Nick Rolfe
2025-06-18 15:32:41 +01:00
parent 8d16d0225c
commit b51940d1e2
54 changed files with 151 additions and 17 deletions

View File

@@ -1,4 +1,6 @@
/** Provides classes for working with locations. */
overlay[local]
module;
import files.FileSystem

View File

@@ -1,4 +1,6 @@
/** Provides classes for working with files and folders. */
overlay[local?]
module;
private import codeql_ql.ast.internal.TreeSitter
private import codeql.Locations

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import ql
private import codeql_ql.ast.internal.TreeSitter
private import experimental.RA
@@ -23,6 +26,7 @@ private float stringToTimestamp(string str) {
}
bindingset[s]
overlay[global]
private Predicate getPredicateFromPosition(string s) {
exists(string r, string filepath, int startline | r = "(.*):(\\d+),(\\d+)-(\\d+),(\\d+)" |
filepath = s.regexpCapture(r, 1) and
@@ -397,6 +401,7 @@ module KindPredicatesLog {
string getPosition() { result = this.getString("position") }
overlay[global]
Predicate getPredicate() { result = getPredicateFromPosition(this.getPosition()) }
/**

View File

@@ -23,6 +23,7 @@ private predicate discardLocation(@location_default loc) {
)
}
overlay[local]
module QL {
/** The base class for all AST nodes */
class AstNode extends @ql_ast_node {
@@ -67,7 +68,6 @@ module QL {
}
/** Gets the file containing the given `node`. */
overlay[local]
private @file getNodeFile(@ql_ast_node node) {
exists(@location_default loc | ql_ast_node_location(node, loc) |
locations_default(loc, result, _, _, _, _)
@@ -75,7 +75,6 @@ module QL {
}
/** Holds if `node` is in the `file` and is part of the overlay base database. */
overlay[local]
private predicate discardableAstNode(@file file, @ql_ast_node node) {
not isOverlay() and file = getNodeFile(node)
}
@@ -1315,6 +1314,7 @@ module QL {
}
}
overlay[local]
module Dbscheme {
/** The base class for all AST nodes */
class AstNode extends @dbscheme_ast_node {
@@ -1359,7 +1359,6 @@ module Dbscheme {
}
/** Gets the file containing the given `node`. */
overlay[local]
private @file getNodeFile(@dbscheme_ast_node node) {
exists(@location_default loc | dbscheme_ast_node_location(node, loc) |
locations_default(loc, result, _, _, _, _)
@@ -1367,7 +1366,6 @@ module Dbscheme {
}
/** Holds if `node` is in the `file` and is part of the overlay base database. */
overlay[local]
private predicate discardableAstNode(@file file, @dbscheme_ast_node node) {
not isOverlay() and file = getNodeFile(node)
}
@@ -1673,6 +1671,7 @@ module Dbscheme {
}
}
overlay[local]
module Blame {
/** The base class for all AST nodes */
class AstNode extends @blame_ast_node {
@@ -1717,7 +1716,6 @@ module Blame {
}
/** Gets the file containing the given `node`. */
overlay[local]
private @file getNodeFile(@blame_ast_node node) {
exists(@location_default loc | blame_ast_node_location(node, loc) |
locations_default(loc, result, _, _, _, _)
@@ -1725,7 +1723,6 @@ module Blame {
}
/** Holds if `node` is in the `file` and is part of the overlay base database. */
overlay[local]
private predicate discardableAstNode(@file file, @blame_ast_node node) {
not isOverlay() and file = getNodeFile(node)
}
@@ -1808,6 +1805,7 @@ module Blame {
}
}
overlay[local]
module JSON {
/** The base class for all AST nodes */
class AstNode extends @json_ast_node {
@@ -1852,7 +1850,6 @@ module JSON {
}
/** Gets the file containing the given `node`. */
overlay[local]
private @file getNodeFile(@json_ast_node node) {
exists(@location_default loc | json_ast_node_location(node, loc) |
locations_default(loc, result, _, _, _, _)
@@ -1860,7 +1857,6 @@ module JSON {
}
/** Holds if `node` is in the `file` and is part of the overlay base database. */
overlay[local]
private predicate discardableAstNode(@file file, @json_ast_node node) {
not isOverlay() and file = getNodeFile(node)
}

View File

@@ -1,6 +1,5 @@
/**
* Parses RA expressions.
*/
overlay[local]
module;
/**
* A predicate that contains RA.

View File

@@ -6,6 +6,7 @@ import ql
import codeql_ql.StructuredLogs
import KindPredicatesLog
overlay[local]
module SumCounts implements Fold<int> {
int base(PipeLineRun run) { result = sum(int i | | run.getCount(i)) }

View File

@@ -1,5 +1,6 @@
import experimental.RA
overlay[local]
class TestPredicate extends string {
TestPredicate() { this = "p1" }

View File

@@ -1,4 +1,6 @@
/** Provides classes for working with locations. */
overlay[local]
module;
import files.FileSystem

View File

@@ -1,4 +1,6 @@
/** Provides classes for working with files and folders. */
overlay[local]
module;
private import codeql.Locations
private import codeql.util.FileSystem

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
import codeql.Locations
import ast.Call
import ast.Control

View File

@@ -1,4 +1,6 @@
/** Provides classes relating to extraction diagnostics. */
overlay[local]
module;
private import codeql.Locations

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import internal.AST
private import internal.Call
@@ -52,6 +55,7 @@ class Call extends Expr instanceof CallImpl {
final int getNumberOfArguments() { result = super.getNumberOfArgumentsImpl() }
/** Gets a potential target of this call, if any. */
overlay[global]
final Callable getATarget() {
exists(DataFlowCall c |
this = c.asCall().getExpr() and
@@ -153,6 +157,7 @@ class MethodCall extends Call instanceof MethodCallImpl {
* TODO: When API Graphs is able to resolve calls to methods like `Kernel.send`
* this class is no longer necessary and should be removed.
*/
overlay[global]
class UnknownMethodCall extends MethodCall {
UnknownMethodCall() { not exists(this.(Call).getATarget()) }
}

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import internal.AST
private import internal.Constant

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import internal.AST
private import internal.Control

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import internal.Erb
private import internal.TreeSitter

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import codeql.ruby.CFG
private import internal.AST

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import codeql.ruby.Regexp as RE
private import internal.AST
@@ -387,6 +390,7 @@ class RegExpLiteral extends StringlikeLiteral instanceof RegExpLiteralImpl {
final predicate hasFreeSpacingFlag() { this.getFlagString().charAt(_) = "x" }
/** Returns the root node of the parse tree of this regular expression. */
overlay[global]
final RE::RegExpTerm getParsed() { result = RE::getParsedRegExp(this) }
}

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import codeql.ruby.controlflow.ControlFlowGraph
private import internal.AST

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import codeql.ruby.CFG
private import internal.AST

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import internal.AST
private import internal.TreeSitter

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import internal.AST
private import internal.Variable

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import internal.AST
private import internal.Pattern

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import internal.AST
private import internal.Scope

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import codeql.ruby.CFG
private import internal.AST

View File

@@ -1,4 +1,6 @@
/** Provides classes for modeling program variables. */
overlay[local]
module;
private import codeql.ruby.AST
private import internal.AST

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
import codeql.Locations
private import TreeSitter
private import codeql.ruby.ast.internal.Call

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import TreeSitter
private import Variable
private import codeql.ruby.AST

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import codeql.ruby.ast.internal.AST
private import codeql.ruby.ast.internal.Literal

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import TreeSitter
private import codeql.ruby.AST
private import codeql.ruby.ast.internal.AST

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
import codeql.Locations
private import TreeSitter
private import codeql.ruby.ast.Erb

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import codeql.ruby.CFG
private import AST

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import AST
private import Constant

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import AST
private import TreeSitter

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import Scope as Scope

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import AST
private import TreeSitter

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import AST
private import TreeSitter

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.AST
private import codeql.ruby.ast.internal.Expr
private import codeql.ruby.ast.internal.Parameter

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import TreeSitter
private import codeql.ruby.AST
private import codeql.ruby.ast.internal.AST

View File

@@ -1,4 +1,6 @@
/** Provides predicates for synthesizing AST nodes. */
overlay[local]
module;
private import AST
private import TreeSitter

View File

@@ -23,6 +23,7 @@ private predicate discardLocation(@location_default loc) {
)
}
overlay[local]
module Ruby {
/** The base class for all AST nodes */
class AstNode extends @ruby_ast_node {
@@ -67,7 +68,6 @@ module Ruby {
}
/** Gets the file containing the given `node`. */
overlay[local]
private @file getNodeFile(@ruby_ast_node node) {
exists(@location_default loc | ruby_ast_node_location(node, loc) |
locations_default(loc, result, _, _, _, _)
@@ -75,7 +75,6 @@ module Ruby {
}
/** Holds if `node` is in the `file` and is part of the overlay base database. */
overlay[local]
private predicate discardableAstNode(@file file, @ruby_ast_node node) {
not isOverlay() and file = getNodeFile(node)
}
@@ -1967,6 +1966,7 @@ module Ruby {
}
}
overlay[local]
module Erb {
/** The base class for all AST nodes */
class AstNode extends @erb_ast_node {
@@ -2011,7 +2011,6 @@ module Erb {
}
/** Gets the file containing the given `node`. */
overlay[local]
private @file getNodeFile(@erb_ast_node node) {
exists(@location_default loc | erb_ast_node_location(node, loc) |
locations_default(loc, result, _, _, _, _)
@@ -2019,7 +2018,6 @@ module Erb {
}
/** Holds if `node` is in the `file` and is part of the overlay base database. */
overlay[local]
private predicate discardableAstNode(@file file, @erb_ast_node node) {
not isOverlay() and file = getNodeFile(node)
}

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import TreeSitter
private import codeql.ruby.AST
private import codeql.ruby.CFG

View File

@@ -1,4 +1,6 @@
/** Provides classes representing basic blocks. */
overlay[local]
module;
private import codeql.ruby.AST
private import codeql.ruby.ast.internal.AST

View File

@@ -1,4 +1,6 @@
/** Provides classes representing nodes in a control flow graph. */
overlay[local]
module;
private import codeql.ruby.AST
private import codeql.ruby.controlflow.BasicBlocks

View File

@@ -1,4 +1,6 @@
/** Provides classes representing the control flow graph. */
overlay[local]
module;
private import codeql.ruby.AST
private import codeql.ruby.controlflow.BasicBlocks

View File

@@ -3,6 +3,8 @@
*
* A completion represents how a statement or expression terminates.
*/
overlay[local]
module;
private import codeql.ruby.AST
private import codeql.ruby.ast.internal.AST

View File

@@ -2,6 +2,8 @@
* Provides an implementation for constructing control-flow graphs (CFGs) from
* abstract syntax trees (ASTs), using the shared library from `codeql.controlflow.Cfg`.
*/
overlay[local]
module;
private import codeql.controlflow.Cfg as CfgShared
private import codeql.ruby.AST

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ruby.CFG
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */

View File

@@ -1,4 +1,6 @@
/** Provides a simple analysis for identifying calls that will not return. */
overlay[local]
module;
private import codeql.ruby.AST
private import Completion

View File

@@ -1,6 +1,8 @@
/**
* Provides classes and predicates relevant for splitting the control flow graph.
*/
overlay[local]
module;
private import codeql.ruby.AST as Ast
private import Completion as Comp

View File

@@ -1,6 +1,8 @@
/**
* Provides the module `Ssa` for working with static single assignment (SSA) form.
*/
overlay[local]
module;
/**
* Provides classes for working with static single assignment (SSA) form.

View File

@@ -1,3 +1,6 @@
overlay[local]
module;
private import codeql.ssa.Ssa as SsaImplCommon
private import codeql.ruby.AST
private import codeql.ruby.CFG as Cfg
@@ -393,6 +396,7 @@ private module Cached {
signature predicate guardChecksSig(Cfg::CfgNodes::AstCfgNode g, Cfg::CfgNode e, boolean branch);
overlay[global]
cached // nothing is actually cached
module BarrierGuard<guardChecksSig/3 guardChecks> {
private predicate guardChecksAdjTypes(

View File

@@ -120,6 +120,7 @@ pub fn generate(
qldoc: None,
name: &language.name,
body,
overlay: Some(ql::OverlayAnnotation::Local),
})],
)?;
}

View File

@@ -95,6 +95,7 @@ pub struct Module<'a> {
pub qldoc: Option<String>,
pub name: &'a str,
pub body: Vec<TopLevel<'a>>,
pub overlay: Option<OverlayAnnotation>,
}
impl fmt::Display for Module<'_> {
@@ -102,6 +103,14 @@ impl fmt::Display for Module<'_> {
if let Some(qldoc) = &self.qldoc {
write!(f, "/** {} */", qldoc)?;
}
if let Some(overlay_annotation) = &self.overlay {
write!(f, "overlay[")?;
match overlay_annotation {
OverlayAnnotation::Local => write!(f, "local")?,
OverlayAnnotation::DiscardEntity => write!(f, "discard_entity")?,
}
write!(f, "] ")?;
}
writeln!(f, "module {} {{ ", self.name)?;
for decl in &self.body {
writeln!(f, " {}", decl)?;

View File

@@ -286,7 +286,7 @@ pub fn create_get_node_file_predicate<'a>(
overridden: false,
is_private: true,
is_final: false,
overlay: Some(ql::OverlayAnnotation::Local),
overlay: None,
return_type: Some(ql::Type::At("file")),
formal_parameters: vec![ql::FormalParameter {
name: "node",
@@ -327,7 +327,7 @@ pub fn create_discardable_ast_node_predicate(ast_node_name: &str) -> ql::Predica
overridden: false,
is_private: true,
is_final: false,
overlay: Some(ql::OverlayAnnotation::Local),
overlay: None,
return_type: None,
formal_parameters: vec![
ql::FormalParameter {