Skip to content

Commit b31f705

Browse files
committed
QL: resolve calls to db relations
1 parent bc74af7 commit b31f705

3 files changed

Lines changed: 82 additions & 4 deletions

File tree

ql/src/codeql_ql/ast/Ast.qll

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,45 @@ class Predicate extends TPredicate, AstNode, Declaration {
232232
override string getAPrimaryQlClass() { result = "Predicate" }
233233
}
234234

235+
/**
236+
* A relation in the database.
237+
*/
238+
class Relation extends TDBRelation, AstNode, Declaration {
239+
Generated::DbTable table;
240+
241+
Relation() { this = TDBRelation(table) }
242+
243+
/**
244+
* Gets the name of the relation.
245+
*/
246+
override string getName() { result = table.getTableName().getChild().getValue() }
247+
248+
private Generated::DbColumn getColumn(int i) {
249+
result =
250+
rank[i + 1](Generated::DbColumn column, int child |
251+
table.getChild(child) = column
252+
|
253+
column order by child
254+
)
255+
}
256+
257+
/** Gets the `i`th parameter name */
258+
string getParameterName(int i) { result = getColumn(i).getColName().getValue() }
259+
260+
/** Gets the `i`th parameter type */
261+
string getParameterType(int i) {
262+
// TODO: This is just using the name of the type, not the actual type. Checkout Type.qll
263+
result = getColumn(i).getColType().getChild().(Generated::Token).getValue()
264+
}
265+
266+
/**
267+
* Gets the number of parameters.
268+
*/
269+
int getArity() { result = count(getColumn(_)) }
270+
271+
override string getAPrimaryQlClass() { result = "Relation" }
272+
}
273+
235274
/**
236275
* An expression that refers to a predicate, e.g. `BasicBlock::succ/2`.
237276
*/
@@ -2154,9 +2193,6 @@ module YAML {
21542193
/** Gets the version of this qlpack */
21552194
string getVersion() { result = getProperty("version") }
21562195

2157-
/** Gets the database scheme of this qlpack */
2158-
string getDbScheme() { result = getProperty("dbscheme") }
2159-
21602196
/** Gets the extractor of this qlpack */
21612197
string getExtractor() { result = getProperty("extractor") }
21622198

@@ -2190,6 +2226,19 @@ module YAML {
21902226
)
21912227
}
21922228

2229+
/** Gets the database scheme of this qlpack */
2230+
File getDBScheme() {
2231+
result.getBaseName() = getProperty("dbscheme") and
2232+
result = file.getParentContainer().getFile(any(string s | s.matches("%.dbscheme")))
2233+
}
2234+
2235+
pragma[noinline]
2236+
Container getAFileInPack() {
2237+
result.getParentContainer() = file.getParentContainer()
2238+
or
2239+
result = getAFileInPack().(Folder).getAChildContainer()
2240+
}
2241+
21932242
/**
21942243
* Gets a QLPack that this QLPack depends on.
21952244
*/

ql/src/codeql_ql/ast/internal/AstNodes.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ newtype TAstNode =
1010
TClass(Generated::Dataclass dc) or
1111
TCharPred(Generated::Charpred pred) or
1212
TClassPredicate(Generated::MemberPredicate pred) or
13+
TDBRelation(Generated::DbTable table) or
1314
TSelect(Generated::Select sel) or
1415
TModule(Generated::Module mod) or
1516
TNewType(Generated::Datatype dt) or
@@ -153,6 +154,8 @@ Generated::AstNode toGenerated(AST::AstNode n) {
153154
or
154155
n = TClassPredicate(result)
155156
or
157+
n = TDBRelation(result)
158+
or
156159
n = TSelect(result)
157160
or
158161
n = TModule(result)
@@ -184,7 +187,7 @@ Generated::AstNode toGenerated(AST::AstNode n) {
184187
n = TSuper(result)
185188
}
186189

187-
class TPredicate = TCharPred or TClasslessPredicate or TClassPredicate;
190+
class TPredicate = TCharPred or TClasslessPredicate or TClassPredicate or TDBRelation;
188191

189192
class TModuleMember = TModuleDeclaration or TImport or TSelect or TQLDoc;
190193

ql/src/codeql_ql/ast/internal/Predicate.qll

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,37 @@ private module Cached {
8888
)
8989
}
9090

91+
pragma[noinline]
92+
private predicate candidate(Relation rel, PredicateCall pc) {
93+
rel.getName() = pc.getPredicateName()
94+
}
95+
96+
private predicate resolveDBRelation(PredicateCall pc, DefinedPredicate p) {
97+
exists(Relation rel | p = TPred(rel) |
98+
candidate(rel, pc) and
99+
rel.getArity() = pc.getNumberOfArguments() and
100+
(
101+
exists(YAML::QLPack libPack, YAML::QLPack qlPack |
102+
rel.getLocation().getFile() = libPack.getDBScheme() and
103+
qlPack.getADependency*() = libPack and
104+
qlPack.getAFileInPack() = pc.getLocation().getFile()
105+
)
106+
or
107+
// upgrade scripts don't have a qlpack
108+
rel.getLocation().getFile().getParentContainer() =
109+
pc.getLocation().getFile().getParentContainer()
110+
)
111+
)
112+
}
113+
91114
cached
92115
predicate resolveCall(Call c, PredicateOrBuiltin p) {
93116
resolvePredicateCall(c, p)
94117
or
95118
resolveMemberCall(c, p)
119+
or
120+
not resolvePredicateCall(c, _) and
121+
resolveDBRelation(c, p)
96122
}
97123

98124
cached

0 commit comments

Comments
 (0)