Skip to content

Commit 7ac467d

Browse files
committed
QL: ql/unqueryable-code query
1 parent b45f56a commit 7ac467d

File tree

2 files changed

+54
-7
lines changed

2 files changed

+54
-7
lines changed

ql/ql/src/codeql_ql/style/DeadCodeQuery.qll

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ private AstNode publicApi() {
3030
*/
3131
private AstNode queryPredicate() {
3232
// result = query relation that is "transitively" imported by a .ql file.
33-
PathProblemQuery::importsQueryRelation(result).asFile().getExtension() = "ql"
33+
// PathProblemQuery::importsQueryRelation(result).asFile().getExtension() = "ql"
34+
// any query predicate. Query predicates are usually meant to be used.
35+
result.(Predicate).hasAnnotation("query")
3436
or
3537
// the from-where-select
3638
result instanceof Select
@@ -200,7 +202,8 @@ private AstNode benign() {
200202
result instanceof BlockComment or
201203
not exists(result.toString()) or // <- invalid code
202204
// cached-stages pattern
203-
result.(Module).getAMember().(ClasslessPredicate).getName() = "forceStage" or
205+
result.(Module).getAMember().(ClasslessPredicate).getName() =
206+
["forceStage", "forceCachingInSameStage"] or
204207
result.(ClasslessPredicate).getName() = "forceStage" or
205208
result.getLocation().getFile().getBaseName() = "Caching.qll" or
206209
// sometimes contains dead code - ignore
@@ -239,16 +242,39 @@ private AstNode queryable() {
239242
result = aliveStep(queryable())
240243
}
241244

245+
// The benign cases are mostly
246+
private AstNode benignUnqueryable() {
247+
result = benign() or
248+
// cached-stages pattern
249+
// sometimes contains dead code - ignore
250+
result.(Module).getName() = "Debugging" or
251+
result.getLocation().getFile() = benignUnqueryableFile()
252+
}
253+
254+
pragma[noinline]
255+
private File benignUnqueryableFile() {
256+
result.getAbsolutePath().matches("%/explore/%") or
257+
result.getRelativePath().matches("%/tutorials/%") or
258+
result.getBaseName() =
259+
[
260+
"Expr.qll", "TypeScript.qll", "YAML.qll", "Tokens.qll", "Instruction.qll", "Persistence.qll",
261+
"ES2015Modules.qll"
262+
] or // lots of classes that exist for completeness
263+
result.getBaseName() = ["CachedStages.qll", "Caching.qll", "tutorial.qll"] or
264+
result.getBaseName().matches("DataFlowImpl%") or // DataFlow has 1578 unqueryable things.
265+
result.getBaseName().matches("SsaImplCommon%") or
266+
result.getBaseName().matches("FlowSummary%") or // Lots of unused FlowSummary stuff in ruby.
267+
not result.getExtension() = ["ql", "qll"] // ignore dbscheme files
268+
}
269+
242270
/**
243271
* Gets an AstNode that does not affect any query result.
244272
* Is interresting as an quick-eval target to investigate dead code.
245273
* (It is intentional that this predicate is a result of this predicate).
246274
*/
247-
AstNode unQueryable(string msg) {
275+
AstNode unQueryable() {
248276
not result = queryable() and
249277
not result = deprecated() and
250-
not result = benign() and
251-
not result.getParent() = any(AstNode node | not node = queryable()) and
252-
msg = result.getLocation().getFile().getBaseName() and
253-
result.getLocation().getFile().getAbsolutePath().matches("%/javascript/%")
278+
not result = benignUnqueryable() and
279+
not result.getParent() = any(AstNode node | not node = queryable())
254280
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* @name Unqueryable code
3+
* @description Code that cannot affect the outcome of any query is suspicous.
4+
* @kind problem
5+
* @problem.severity recommendation
6+
* @id ql/unqueryable-code
7+
* @precision high
8+
*/
9+
10+
import ql
11+
import codeql_ql.style.DeadCodeQuery
12+
13+
from AstNode node
14+
where
15+
node = unQueryable() and
16+
// the static languages have way too much noise from code that is only queried from internal stuff
17+
node.getLocation()
18+
.getFile()
19+
.getAbsolutePath()
20+
.matches("%/" + ["javascript", "python", "ruby"] + "/%")
21+
select node, "Code cannot affect the outcome of any query."

0 commit comments

Comments
 (0)