forked from github/codeql
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathUnreachableCode.ql
More file actions
78 lines (70 loc) · 1.97 KB
/
UnreachableCode.ql
File metadata and controls
78 lines (70 loc) · 1.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/**
* @name Unreachable code
* @description Code that cannot be reached should be deleted.
* @kind problem
* @problem.severity recommendation
* @precision medium
* @id rust/dead-code
* @tags maintainability
* quality
*/
import rust
import codeql.rust.controlflow.ControlFlowGraph
import codeql.rust.controlflow.internal.ControlFlowGraphImpl as ControlFlowGraphImpl
/**
* Successor relation that includes unreachable AST nodes.
*/
private predicate succ(AstNode a, AstNode b) {
exists(ControlFlowGraphImpl::ControlFlowTree cft | cft.succ(a, b, _))
}
/**
* Gets a node we'd prefer not to report as unreachable. These will be removed
* from the AST for the purposes of this query, with successor links being
* made across them where appropriate.
*/
predicate hiddenNode(AstNode n) {
// isolated node (not intended to be part of the CFG)
not succ(n, _) and
not succ(_, n)
or
n instanceof ControlFlowGraphImpl::PostOrderTree and // location is counter-intuitive
not n instanceof MacroExpr
or
n.isFromMacroExpansion()
}
/**
* Successor relation for edges out of `hiddenNode`s.
*/
private predicate succHidden(AstNode a, AstNode b) {
hiddenNode(a) and
succ(a, b)
}
/**
* Successor relation that removes / links over `hiddenNode`s.
*/
private predicate succWithHiding(AstNode a, AstNode b) {
exists(AstNode mid |
not hiddenNode(a) and
succ(a, mid) and
succHidden*(mid, b) and
not hiddenNode(b)
)
}
/**
* An AST node that is reachable.
*/
predicate reachable(AstNode n) { n = any(CfgNode cfn).getAstNode() }
/**
* Holds if `n` is an AST node that's unreachable, and any predecessors
* of it are reachable (to avoid duplicate results).
*/
private predicate firstUnreachable(AstNode n) {
not reachable(n) and
not hiddenNode(n) and
forall(AstNode pred | succWithHiding(pred, n) | reachable(pred))
}
from AstNode n
where
firstUnreachable(n) and
exists(n.getFile().getRelativePath()) // in source
select n, "This code is never reached."