Skip to content

Commit 2d640e7

Browse files
committed
QL: Add basic data flow nodes
1 parent c9b9751 commit 2d640e7

File tree

2 files changed

+166
-0
lines changed

2 files changed

+166
-0
lines changed
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
private import codeql_ql.ast.Ast
2+
private import internal.NodesInternal
3+
4+
/**
5+
* An expression or variable in a formula, including some additional nodes
6+
* that are not part of the AST.
7+
*/
8+
class Node extends TNode {
9+
string toString() { none() } // overridden in subclasses
10+
Location getLocation() { none() } // overridden in subclasses
11+
12+
/**
13+
* Gets the underlying `Expr` or `VarDef` node, if this is an `AstNodeNode`.
14+
*/
15+
AstNode asAstNode() { astNode(result) = this }
16+
}
17+
18+
/**
19+
* A data-flow node based an `Expr` or `VarDef` AST node.
20+
*/
21+
class AstNodeNode extends Node, MkAstNodeNode {
22+
private AstNode ast;
23+
24+
AstNodeNode() { this = MkAstNodeNode(ast) }
25+
26+
override string toString() {
27+
result = ast.toString()
28+
}
29+
30+
override Location getLocation() {
31+
result = ast.getLocation()
32+
}
33+
34+
/** Gets the AST node. */
35+
AstNode getAstNode() {
36+
result = ast
37+
}
38+
}
39+
40+
/**
41+
* Gets the data-flow node correspoinding to the given AST node.
42+
*/
43+
pragma[inline]
44+
Node astNode(AstNode node) {
45+
result = MkAstNodeNode(node)
46+
}
47+
48+
/**
49+
* A data-flow node representing `this` within a class predicate, charpred, or newtype branch.
50+
*/
51+
class ThisNode extends Node, MkThisNode {
52+
private Predicate pred;
53+
54+
ThisNode() { this = MkThisNode(pred) }
55+
56+
override string toString() {
57+
result = "'this' in " + pred.getName()
58+
}
59+
60+
override Location getLocation() {
61+
result = pred.getLocation()
62+
}
63+
64+
/** Gets the class predicate, charpred, or newtype branch whose 'this' parameter is represented by this node. */
65+
Predicate getPredicate() {
66+
result = pred
67+
}
68+
}
69+
70+
/**
71+
* Gets the data-flow node representing `this` within the given class predicate, charpred, or newtype branch.
72+
*/
73+
pragma[inline]
74+
Node thisNode(Predicate pred) {
75+
result = MkThisNode(pred)
76+
}
77+
78+
/**
79+
* A data-flow node representing `result` within a predicate that has a result.
80+
*/
81+
class ResultNode extends Node, MkResultNode {
82+
private Predicate pred;
83+
84+
ResultNode() { this = MkResultNode(pred) }
85+
86+
override string toString() {
87+
result = "'result' in " + pred.getName()
88+
}
89+
90+
override Location getLocation() {
91+
result = pred.getLocation()
92+
}
93+
94+
/** Gets the predicate whose 'result' parameter is represented by this node. */
95+
Predicate getPredicate() {
96+
result = pred
97+
}
98+
}
99+
100+
/**
101+
* Gets the data-flow node representing `result` within the given predicate.
102+
*/
103+
pragma[inline]
104+
Node resultNode(Predicate pred) {
105+
result = MkResultNode(pred)
106+
}
107+
108+
/**
109+
* A data-flow node representing the view of a field in the enclosing class, as seen
110+
* from a charpred or class predicate.
111+
*/
112+
class FieldNode extends Node, MkFieldNode {
113+
private Predicate pred;
114+
private FieldDecl fieldDecl;
115+
116+
FieldNode() { this = MkFieldNode(pred, fieldDecl) }
117+
118+
/** Gets the member predicate or charpred for which this node represents access to the field. */
119+
Predicate getPredicate() {
120+
result = pred
121+
}
122+
123+
FieldDecl getFieldDeclaration() {
124+
result = fieldDecl
125+
}
126+
127+
string getFieldName() {
128+
result = fieldDecl.getName()
129+
}
130+
131+
override string toString() {
132+
result = "'" + this.getFieldName() + "' in " + pred.getName()
133+
}
134+
135+
override Location getLocation() {
136+
result = pred.getLocation()
137+
}
138+
}
139+
140+
/**
141+
* Gets the data-flow node representing the given predicate's view of the given field
142+
* in the enclosing class.
143+
*/
144+
pragma[inline]
145+
Node fieldNode(Predicate pred, FieldDecl fieldDecl) {
146+
result = MkFieldNode(pred, fieldDecl)
147+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
private import codeql_ql.ast.Ast
2+
3+
newtype TNode =
4+
MkAstNodeNode(AstNode node) {
5+
node instanceof Expr or
6+
node instanceof VarDef
7+
} or
8+
MkThisNode(Predicate pred) {
9+
pred instanceof ClassPredicate or
10+
pred instanceof CharPred or
11+
pred instanceof NewTypeBranch
12+
} or
13+
MkResultNode(Predicate pred) { exists(pred.getReturnTypeExpr()) } or
14+
MkFieldNode(Predicate pred, FieldDecl fieldDecl) {
15+
// TODO: should this be omitted when the field is not referenced?
16+
fieldDecl.getVarDecl() = pred.(ClassPredicate).getDeclaringType().getField(_)
17+
or
18+
fieldDecl.getVarDecl() = pred.(CharPred).getDeclaringType().getField(_)
19+
}

0 commit comments

Comments
 (0)