Skip to content

Commit 28d2dae

Browse files
authored
QL: Merge pull request #24 from github/types
Resolve calls
2 parents c33e0a5 + 17f6cad commit 28d2dae

5 files changed

Lines changed: 197 additions & 97 deletions

File tree

ql/src/codeql_ql/ast/Ast.qll

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ bindingset[name]
99
private string directMember(string name) { result = name + "()" }
1010

1111
bindingset[name, i]
12-
private string indexedMember(string name, int i) { result = name + "(_)" }
12+
private string indexedMember(string name, int i) { result = name + "(_)" and exists(i) }
1313

1414
bindingset[name, index]
15-
private string stringIndexedMember(string name, string index) { result = name + "(_)" }
15+
private string stringIndexedMember(string name, string index) {
16+
result = name + "(_)" and exists(index)
17+
}
1618

1719
/** An AST node of a QL program */
1820
class AstNode extends TAstNode {
@@ -110,17 +112,18 @@ class Predicate extends TPredicate, AstNode {
110112
/**
111113
* Gets the return type (if any) of the predicate.
112114
*/
113-
TypeExpr getReturnType() { none() }
115+
TypeExpr getReturnTypeExpr() { none() }
116+
117+
Type getReturnType() { result = this.getReturnTypeExpr().getResolvedType() }
114118

115-
// TODO: ReturnType.
116119
override AstNode getAChild(string pred) {
117120
result = super.getAChild(pred)
118121
or
119122
pred = directMember("getBody") and result = this.getBody()
120123
or
121124
exists(int i | pred = indexedMember("getParameter", i) and result = this.getParameter(i))
122125
or
123-
pred = directMember("getReturnType") and result = this.getReturnType()
126+
pred = directMember("getReturnTypeExpr") and result = this.getReturnTypeExpr()
124127
}
125128

126129
override string getAPrimaryQlClass() { result = "Predicate" }
@@ -199,7 +202,7 @@ class ClasslessPredicate extends TClasslessPredicate, Predicate, ModuleDeclarati
199202
rank[i](Generated::VarDecl decl, int index | decl = pred.getChild(index) | decl order by index)
200203
}
201204

202-
override TypeExpr getReturnType() { toGenerated(result) = pred.getReturnType() }
205+
override TypeExpr getReturnTypeExpr() { toGenerated(result) = pred.getReturnType() }
203206

204207
override AstNode getAChild(string pred_name) {
205208
result = Predicate.super.getAChild(pred_name)
@@ -210,7 +213,7 @@ class ClasslessPredicate extends TClasslessPredicate, Predicate, ModuleDeclarati
210213
or
211214
exists(int i | pred_name = indexedMember("getParameter", i) and result = this.getParameter(i))
212215
or
213-
pred_name = directMember("getReturnType") and result = this.getReturnType()
216+
pred_name = directMember("getReturnTypeExpr") and result = this.getReturnTypeExpr()
214217
}
215218
}
216219

@@ -248,7 +251,7 @@ class ClassPredicate extends TClassPredicate, Predicate {
248251

249252
predicate overrides(ClassPredicate other) { predOverrides(this, other) }
250253

251-
override TypeExpr getReturnType() { toGenerated(result) = pred.getReturnType() }
254+
override TypeExpr getReturnTypeExpr() { toGenerated(result) = pred.getReturnType() }
252255

253256
override AstNode getAChild(string pred_name) {
254257
result = super.getAChild(pred_name)
@@ -257,7 +260,7 @@ class ClassPredicate extends TClassPredicate, Predicate {
257260
or
258261
exists(int i | pred_name = indexedMember("getParameter", i) and result = this.getParameter(i))
259262
or
260-
pred_name = directMember("getReturnType") and result = this.getReturnType()
263+
pred_name = directMember("getReturnTypeExpr") and result = this.getReturnTypeExpr()
261264
}
262265
}
263266

@@ -290,6 +293,8 @@ class VarDef extends TVarDef, AstNode {
290293
/** Gets the name of the declared variable. */
291294
string getName() { none() }
292295

296+
Type getType() { none() }
297+
293298
override string getAPrimaryQlClass() { result = "VarDef" }
294299

295300
override string toString() { result = this.getName() }
@@ -305,9 +310,11 @@ class VarDecl extends TVarDecl, VarDef {
305310

306311
override string getName() { result = var.getChild(1).(Generated::VarName).getChild().getValue() }
307312

313+
override Type getType() { result = this.getTypeExpr().getResolvedType() }
314+
308315
override string getAPrimaryQlClass() { result = "VarDecl" }
309316

310-
TypeExpr getType() { toGenerated(result) = var.getChild(0) }
317+
TypeExpr getTypeExpr() { toGenerated(result) = var.getChild(0) }
311318

312319
predicate isPrivate() {
313320
exists(Generated::ClassMember member |
@@ -324,7 +331,7 @@ class VarDecl extends TVarDecl, VarDef {
324331
override AstNode getAChild(string pred) {
325332
result = super.getAChild(pred)
326333
or
327-
pred = directMember("getType") and result = this.getType()
334+
pred = directMember("getTypeExpr") and result = this.getTypeExpr()
328335
}
329336
}
330337

@@ -588,11 +595,17 @@ class NewTypeBranch extends TNewTypeBranch, TypeDeclaration {
588595
}
589596
}
590597

591-
class Call extends TCall, AstNode {
598+
class Call extends TCall, Expr {
592599
Expr getArgument(int i) {
593600
none() // overriden in sublcasses.
594601
}
595602

603+
Predicate getTarget() { resolveCall(this, result) }
604+
605+
override Type getType() { result = this.getTarget().getReturnType() }
606+
607+
final int getNumberOfArguments() { result = count(this.getArgument(_)) }
608+
596609
ModuleExpr getQualifier() { none() }
597610
}
598611

@@ -677,6 +690,8 @@ class NoneCall extends TNoneCall, Call, Formula {
677690
NoneCall() { this = TNoneCall(call) }
678691

679692
override string getAPrimaryQlClass() { result = "NoneCall" }
693+
694+
override AstNode getParent() { result = Call.super.getParent() }
680695
}
681696

682697
class AnyCall extends TAnyCall, Call {
@@ -694,16 +709,18 @@ class InlineCast extends TInlineCast, Expr {
694709

695710
override string getAPrimaryQlClass() { result = "InlineCast" }
696711

697-
TypeExpr getType() {
712+
TypeExpr getTypeExpr() {
698713
toGenerated(result) = expr.getChild(_).(Generated::QualifiedRhs).getChild(_)
699714
}
700715

716+
override Type getType() { result = this.getTypeExpr().getResolvedType() }
717+
701718
Expr getBase() { toGenerated(result) = expr.getChild(0) }
702719

703720
override AstNode getAChild(string pred) {
704721
result = super.getAChild(pred)
705722
or
706-
pred = directMember("getType") and result = this.getType()
723+
pred = directMember("getTypeExpr") and result = this.getTypeExpr()
707724
or
708725
pred = directMember("getBase") and result = this.getBase()
709726
}
@@ -1185,6 +1202,14 @@ class Aggregate extends TAggregate, Expr {
11851202

11861203
override string getAPrimaryQlClass() { result = "Aggregate[" + kind + "]" }
11871204

1205+
override PrimitiveType getType() {
1206+
kind.regexpMatch("(strict)?count|sum|min|max|rank") and
1207+
result.getName() = "int"
1208+
or
1209+
kind.regexpMatch("(strict)?concat") and
1210+
result.getName() = "string"
1211+
}
1212+
11881213
override AstNode getAChild(string pred) {
11891214
result = super.getAChild(pred)
11901215
or
@@ -1232,6 +1257,8 @@ class AsExpr extends TAsExpr, VarDef, Expr {
12321257

12331258
final override string getName() { result = this.getAsName() }
12341259

1260+
final override Type getType() { result = this.getInnerExpr().getType() }
1261+
12351262
/**
12361263
* Gets the name the inner expression gets "saved" under.
12371264
* For example this is `bar` in the expression `foo as bar`.
@@ -1274,6 +1301,8 @@ class VarAccess extends Identifier {
12741301

12751302
override string getName() { result = id.getChild().(Generated::VarName).getChild().getValue() }
12761303

1304+
override Type getType() { result = this.getDeclaration().getType() }
1305+
12771306
override string getAPrimaryQlClass() { result = "VarAccess" }
12781307
}
12791308

@@ -1288,13 +1317,17 @@ class FieldAccess extends Identifier {
12881317

12891318
override string getName() { result = id.getChild().(Generated::VarName).getChild().getValue() }
12901319

1320+
override Type getType() { result = this.getDeclaration().getType() }
1321+
12911322
override string getAPrimaryQlClass() { result = "FieldAccess" }
12921323
}
12931324

12941325
/** An access to `this`. */
12951326
class ThisAccess extends Identifier {
12961327
ThisAccess() { any(Generated::This t).getParent() = id }
12971328

1329+
override Type getType() { result = this.getParent+().(Class).getType() }
1330+
12981331
override string getName() { result = "this" }
12991332

13001333
override string getAPrimaryQlClass() { result = "ThisAccess" }
@@ -1304,6 +1337,8 @@ class ThisAccess extends Identifier {
13041337
class ResultAccess extends Identifier {
13051338
ResultAccess() { any(Generated::Result r).getParent() = id }
13061339

1340+
override Type getType() { result = this.getParent+().(Predicate).getReturnType() }
1341+
13071342
override string getName() { result = "result" }
13081343

13091344
override string getAPrimaryQlClass() { result = "ResultAccess" }
@@ -1328,7 +1363,9 @@ class Negation extends TNegation, Formula {
13281363
}
13291364

13301365
/** An expression, such as `x+4`. */
1331-
class Expr extends TExpr, AstNode { }
1366+
class Expr extends TExpr, AstNode {
1367+
Type getType() { none() }
1368+
}
13321369

13331370
class ExprAnnotation extends TExprAnnotation, Expr {
13341371
Generated::ExprAnnotation expr_anno;
@@ -1590,5 +1627,3 @@ class ModuleExpr extends TModuleExpr, ModuleRef {
15901627
pred = directMember("getQualifier") and result = this.getQualifier()
15911628
}
15921629
}
1593-
1594-
private AstNode noParent() { not exists(result.getParent()) and not result instanceof TopLevel }

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,59 @@ predicate resolvePredicateExpr(PredicateExpr pe, ClasslessPredicate p) {
3838
)
3939
}
4040

41+
private predicate resolvePredicateCall(PredicateCall pc, Predicate p) {
42+
exists(Class c, ClassType t |
43+
c = pc.getParent*() and
44+
t = c.getType() and
45+
p = t.getClassPredicate(pc.getPredicateName(), pc.getNumberOfArguments())
46+
)
47+
or
48+
exists(FileOrModule m, boolean public |
49+
not exists(pc.getQualifier()) and
50+
m = getEnclosingModule(pc).getEnclosing*() and
51+
public = [false, true]
52+
or
53+
m = pc.getQualifier().getResolvedModule() and
54+
public = true
55+
|
56+
definesPredicate(m, pc.getPredicateName(), p, public) and
57+
count(p.getParameter(_)) = pc.getNumberOfArguments()
58+
)
59+
}
60+
61+
private predicate resolveMemberCall(MemberCall mc, Predicate p) {
62+
exists(ClassType t |
63+
t = mc.getBase().getType() and
64+
p = t.getClassPredicate(mc.getMemberName(), mc.getNumberOfArguments())
65+
)
66+
}
67+
68+
predicate resolveCall(Call c, Predicate p) {
69+
resolvePredicateCall(c, p)
70+
or
71+
resolveMemberCall(c, p)
72+
}
73+
4174
module PredConsistency {
4275
query predicate noResolvePredicateExpr(PredicateExpr pe) {
4376
not resolvePredicateExpr(pe, _) and
4477
not pe.getLocation().getFile().getAbsolutePath().regexpMatch(".*/(test|examples)/.*")
4578
}
4679

80+
query predicate noResolveCall(Call c) {
81+
not resolveCall(c, _) and
82+
not c.getLocation().getFile().getAbsolutePath().regexpMatch(".*/(test|examples)/.*")
83+
}
84+
4785
query predicate multipleResolvePredicateExpr(PredicateExpr pe, int c, ClasslessPredicate p) {
4886
c = strictcount(ClasslessPredicate p0 | resolvePredicateExpr(pe, p0)) and
4987
c > 1 and
5088
resolvePredicateExpr(pe, p)
5189
}
90+
91+
query predicate multipleResolveCall(Call call, int c, Predicate p) {
92+
c = strictcount(Predicate p0 | resolveCall(call, p0)) and
93+
c > 1 and
94+
resolveCall(call, p)
95+
}
5296
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,4 +314,18 @@ module TyConsistency {
314314
c > 1 and
315315
resolveTypeExpr(te, t)
316316
}
317+
318+
query predicate varDefNoType(VarDef def) {
319+
not exists(def.getType()) and
320+
not def.getLocation().getFile().getAbsolutePath().regexpMatch(".*/(test|examples)/.*")
321+
}
322+
323+
query predicate exprNoType(Expr e) {
324+
not exists(e.getType()) and
325+
not exists(Predicate p |
326+
p = e.(Call).getTarget() and
327+
not exists(p.getReturnType())
328+
) and
329+
not e.getLocation().getFile().getAbsolutePath().regexpMatch(".*/(test|examples)/.*")
330+
}
317331
}

ql/src/ide-contextual-queries/Definitions.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ private predicate resolveVar(VarAccess va, VarDecl decl, string kind) {
4848
kind = "variable"
4949
}
5050

51+
private predicate resolveCall(Call c, Predicate p, string kind) {
52+
p = c.getTarget() and
53+
kind = "call"
54+
}
55+
5156
cached
5257
predicate resolve(Loc ref, Loc target, string kind) {
5358
resolveModule(ref.asAst(), target.asMod(), kind)
@@ -57,4 +62,6 @@ predicate resolve(Loc ref, Loc target, string kind) {
5762
resolvePredicate(ref.asAst(), target.asAst(), kind)
5863
or
5964
resolveVar(ref.asAst(), target.asAst(), kind)
65+
or
66+
resolveCall(ref.asAst(), target.asAst(), kind)
6067
}

0 commit comments

Comments
 (0)