Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6236522

Browse files
pavgustjbj
authored andcommitted
Introduce partial-definition nodes
1 parent 15b56d9 commit 6236522

3 files changed

Lines changed: 270 additions & 179 deletions

File tree

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ private import DataFlowDispatch
44

55
/** Gets the instance argument of a non-static call. */
66
private Node getInstanceArgument(Call call) {
7-
result.asExpr() = call.getQualifier() or
8-
result.(ImplicitInstancePostCall).getCall() = call
7+
result.asExpr() = call.getQualifier()
98
// This does not include the implicit `this` argument on auto-generated
109
// base class destructor calls as those do not have an AST element.
1110
}
@@ -162,23 +161,6 @@ private class ArrayContent extends Content, TArrayContent {
162161
override Type getType() { none() }
163162
}
164163

165-
/**
166-
* Gets the dataflow node corresponding to the field qualifier of `fa`.
167-
*
168-
* Note that this might be an implicit access to the `this` pointer.
169-
*/
170-
Node getFieldQualifier(FieldAccess fa) {
171-
not fa.getTarget().isStatic() and
172-
(
173-
result.asExpr() = fa.getQualifier() or
174-
result
175-
.(ImplicitInstanceAccess)
176-
.getInstanceAccess()
177-
.(ImplicitThisForFieldAccess)
178-
.getBackingExpr() = fa
179-
)
180-
}
181-
182164
/**
183165
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
184166
* Thus, `node2` references an object with a field `f` that contains the
@@ -191,7 +173,7 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
191173
a.getLValue() = fa
192174
) and
193175
not fa.getTarget().isStatic() and
194-
node2.getPreUpdateNode() = getFieldQualifier(fa) and
176+
node2.getPreUpdateNode().asExpr() = fa.getQualifier() and
195177
f.(FieldContent).getField() = fa.getTarget()
196178
)
197179
}
@@ -203,7 +185,7 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
203185
*/
204186
predicate readStep(Node node1, Content f, Node node2) {
205187
exists(FieldAccess fr |
206-
node1 = getFieldQualifier(fr) and
188+
node1.asExpr() = fr.getQualifier() and
207189
fr.getTarget() = f.(FieldContent).getField() and
208190
fr = node2.asExpr() and
209191
not fr = any(AssignExpr a).getLValue()

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll

Lines changed: 85 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -6,57 +6,12 @@ private import cpp
66
private import semmle.code.cpp.dataflow.internal.FlowVar
77
private import semmle.code.cpp.models.interfaces.DataFlow
88

9-
private newtype TInstanceAccess =
10-
TExplicitThisAccess(ThisExpr e) or
11-
TImplicitThisForFieldAccess(FieldAccess fa) {
12-
not exists(fa.getQualifier()) and not fa.getTarget().isStatic()
13-
} or
14-
TImplicitThisForCall(FunctionCall fc) {
15-
fc.getTarget() instanceof MemberFunction and
16-
not exists(fc.getQualifier()) and
17-
not fc.getTarget().isStatic() and
18-
not fc.getTarget() instanceof Constructor
19-
}
20-
21-
private class InstanceAccess extends TInstanceAccess {
22-
abstract Expr getBackingExpr();
23-
24-
Location getLocation() { result = getBackingExpr().getLocation() }
25-
26-
abstract string toString();
27-
}
28-
29-
class ExplicitThisAccess extends InstanceAccess, TExplicitThisAccess {
30-
override Expr getBackingExpr() { this = TExplicitThisAccess(result) }
31-
32-
override string toString() { result = getBackingExpr().toString() }
33-
}
34-
35-
class ImplicitThisForFieldAccess extends InstanceAccess, TImplicitThisForFieldAccess {
36-
override FieldAccess getBackingExpr() { this = TImplicitThisForFieldAccess(result) }
37-
38-
override string toString() { result = "<implicit this> for field access" }
39-
}
40-
41-
class ImplicitThisForCall extends InstanceAccess, TImplicitThisForCall {
42-
override FunctionCall getBackingExpr() { this = TImplicitThisForCall(result) }
43-
44-
override string toString() { result = "<implicit this> for call" }
45-
}
46-
479
cached
4810
private newtype TNode =
4911
TExprNode(Expr e) or
50-
TParameterNode(Parameter p) { exists(p.getFunction().getBlock()) } or
12+
TPartialDefNode(PartialDefinition pd) or
13+
TExplicitParameterNode(Parameter p) { exists(p.getFunction().getBlock()) } or
5114
TInstanceParameterNode(MemberFunction f) { exists(f.getBlock()) and not f.isStatic() } or
52-
TImplicitInstanceAccessNode(InstanceAccess ia) { not ia instanceof ExplicitThisAccess } or
53-
TImplicitInstancePostCallNode(InstanceAccess a) { a instanceof ImplicitThisForCall } or
54-
TExplicitArgumentPostCallNode(Expr e) {
55-
e = any(Call c).getAnArgument() or
56-
e = any(Call c).getQualifier()
57-
} or
58-
TImplicitInstancePostStoreNode(InstanceAccess a) { a instanceof ImplicitThisForFieldAccess } or
59-
TExplicitInstancePostStoreNode(Expr e) { e = any(FieldAccess f).getQualifier() } or
6015
TDefinitionByReferenceNode(VariableAccess va, Expr argument) {
6116
definitionByReference(va, argument)
6217
} or
@@ -85,11 +40,23 @@ class Node extends TNode {
8540
Expr asExpr() { result = this.(ExprNode).getExpr() }
8641

8742
/** Gets the parameter corresponding to this node, if any. */
88-
Parameter asParameter() { result = this.(ParameterNode).getParameter() }
43+
Parameter asParameter() { result = this.(ExplicitParameterNode).getParameter() }
8944

9045
/** Gets the argument that defines this `DefinitionByReferenceNode`, if any. */
9146
Expr asDefiningArgument() { result = this.(DefinitionByReferenceNode).getArgument() }
9247

48+
/**
49+
* Gets the expression that is partially defined by this node, if any.
50+
*
51+
* Partial definitions are created for field stores (`x.y = taint();` is a partial
52+
* definition of `x`), and for calls that may change the value of an object (so
53+
* `x.set(taint())` is a partial definition of `x`, annd `transfer(&x, taint())` is
54+
* a partial definition of `&x`).s
55+
*/
56+
Expr asPartialDefinition() {
57+
result = this.(PartialDefNode).getPartialDefinition().getDefinedExpr()
58+
}
59+
9360
/**
9461
* Gets the uninitialized local variable corresponding to this node, if
9562
* any.
@@ -128,14 +95,22 @@ class ExprNode extends Node, TExprNode {
12895
Expr getExpr() { result = expr }
12996
}
13097

98+
abstract class ParameterNode extends Node, TNode {
99+
/**
100+
* Holds if this node is the parameter of `c` at the specified (zero-based)
101+
* position. The implicit `this` parameter is considered to have index `-1`.
102+
*/
103+
abstract predicate isParameterOf(Function f, int i);
104+
}
105+
131106
/**
132107
* The value of a parameter at function entry, viewed as a node in a data
133108
* flow graph.
134109
*/
135-
class ParameterNode extends Node, TParameterNode {
110+
class ExplicitParameterNode extends ParameterNode, TExplicitParameterNode {
136111
Parameter param;
137112

138-
ParameterNode() { this = TParameterNode(param) }
113+
ExplicitParameterNode() { this = TExplicitParameterNode(param) }
139114

140115
override Function getFunction() { result = param.getFunction() }
141116

@@ -148,29 +123,23 @@ class ParameterNode extends Node, TParameterNode {
148123
/** Gets the parameter corresponding to this node. */
149124
Parameter getParameter() { result = param }
150125

151-
/**
152-
* Holds if this node is the parameter of `c` at the specified (zero-based)
153-
* position. The implicit `this` parameter is considered to have index `-1`.
154-
*/
155-
predicate isParameterOf(Function f, int i) { f.getParameter(i) = param }
126+
override predicate isParameterOf(Function f, int i) { f.getParameter(i) = param }
156127
}
157128

158-
/**
159-
* The value of the implicit instance parameter (in other words, the `this`
160-
* pointer) at function entry, viewed as a node in a data flow graph.
161-
*/
162-
class InstanceParameterNode extends Node, TInstanceParameterNode {
129+
class ImplicitParameterNode extends ParameterNode, TInstanceParameterNode {
163130
MemberFunction f;
164131

165-
InstanceParameterNode() { this = TInstanceParameterNode(f) }
132+
ImplicitParameterNode() { this = TInstanceParameterNode(f) }
166133

167134
override Function getFunction() { result = f }
168135

169-
override Type getType() { result.(PointerType).getBaseType() = f.getDeclaringType() }
136+
override Type getType() { result = f.getDeclaringType() }
170137

171-
override string toString() { result = "<this> param" }
138+
override string toString() { result = "`this` parameter in " + f.getName() }
172139

173140
override Location getLocation() { result = f.getLocation() }
141+
142+
override predicate isParameterOf(Function fun, int i) { f = fun and i = -1 }
174143
}
175144

176145
/**
@@ -253,40 +222,18 @@ abstract class PostUpdateNode extends Node {
253222
override string toString() { result = getPreUpdateNode().toString() + " [post update]" }
254223
}
255224

256-
class ImplicitInstanceAccess extends Node, TImplicitInstanceAccessNode {
257-
InstanceAccess ia;
258-
259-
ImplicitInstanceAccess() { this = TImplicitInstanceAccessNode(ia) }
260-
261-
override string toString() { result = ia.toString() }
262-
263-
override Location getLocation() { result = ia.getLocation() }
264-
265-
InstanceAccess getInstanceAccess() { result = ia }
266-
}
267-
268-
class ImplicitInstancePostCall extends PostUpdateNode, TImplicitInstancePostCallNode {
269-
ImplicitThisForCall ia;
225+
class PartialDefNode extends PostUpdateNode, TPartialDefNode {
226+
PartialDefinition pd;
270227

271-
ImplicitInstancePostCall() { this = TImplicitInstancePostCallNode(ia) }
228+
PartialDefNode() { this = TPartialDefNode(pd) }
272229

273-
override Node getPreUpdateNode() { ia = result.(ImplicitInstanceAccess).getInstanceAccess() }
230+
override Node getPreUpdateNode() { result.asExpr() = pd.getDefinedExpr() }
274231

275-
FunctionCall getCall() { result = ia.getBackingExpr() }
276-
}
277-
278-
class ExplicitArgPostCall extends PostUpdateNode, TExplicitArgumentPostCallNode {
279-
override Node getPreUpdateNode() { this = TExplicitArgumentPostCallNode(result.asExpr()) }
280-
}
232+
override string toString() { result = pd.toString() }
281233

282-
class ImplicitStoreTarget extends PostUpdateNode, TImplicitInstancePostStoreNode {
283-
override Node getPreUpdateNode() {
284-
this = TImplicitInstancePostStoreNode(result.(ImplicitInstanceAccess).getInstanceAccess())
285-
}
286-
}
234+
override Location getLocation() { result = pd.getLocation() }
287235

288-
class ExplicitStoreTarget extends PostUpdateNode, TExplicitInstancePostStoreNode {
289-
override Node getPreUpdateNode() { this = TExplicitInstancePostStoreNode(result.asExpr()) }
236+
PartialDefinition getPartialDefinition() { result = pd }
290237
}
291238

292239
/**
@@ -297,7 +244,7 @@ ExprNode exprNode(Expr e) { result.getExpr() = e }
297244
/**
298245
* Gets the `Node` corresponding to the value of `p` at function entry.
299246
*/
300-
ParameterNode parameterNode(Parameter p) { result.getParameter() = p }
247+
ParameterNode parameterNode(Parameter p) { result.(ExplicitParameterNode).getParameter() = p }
301248

302249
/**
303250
* Gets the `Node` corresponding to a definition by reference of the variable
@@ -313,6 +260,43 @@ DefinitionByReferenceNode definitionByReferenceNodeFromArgument(Expr argument) {
313260
*/
314261
UninitializedNode uninitializedNode(LocalVariable v) { result.getLocalVariable() = v }
315262

263+
private module ThisFlow {
264+
private Node thisAccessNode(ControlFlowNode cfn) {
265+
result.(ImplicitParameterNode).getFunction().getBlock() = cfn or
266+
result.asExpr().(ThisExpr) = cfn
267+
}
268+
269+
private int basicBlockThisIndex(BasicBlock b, Node thisNode) {
270+
thisNode = thisAccessNode(b.getNode(result))
271+
}
272+
273+
private int thisRank(BasicBlock b, Node thisNode) {
274+
thisNode = rank[result](thisAccessNode(_) as node order by basicBlockThisIndex(b, node))
275+
}
276+
277+
private int lastThisRank(BasicBlock b) { result = max(thisRank(b, _)) }
278+
279+
private predicate thisAccessBlockReaches(BasicBlock b1, BasicBlock b2) {
280+
exists(basicBlockThisIndex(b1, _)) and b2 = b1.getASuccessor()
281+
or
282+
exists(BasicBlock mid |
283+
thisAccessBlockReaches(b1, mid) and
284+
b2 = mid.getASuccessor() and
285+
not exists(basicBlockThisIndex(mid, _))
286+
)
287+
}
288+
289+
predicate adjacentThisRefs(Node n1, Node n2) {
290+
exists(BasicBlock b | thisRank(b, n1) + 1 = thisRank(b, n2))
291+
or
292+
exists(BasicBlock b1, BasicBlock b2 |
293+
lastThisRank(b1) = thisRank(b1, n1) and
294+
thisAccessBlockReaches(b1, b2) and
295+
thisRank(b2, n2) = 1
296+
)
297+
}
298+
}
299+
316300
/**
317301
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
318302
* (intra-procedural) step.
@@ -332,12 +316,20 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) {
332316
varSourceBaseCase(var, nodeFrom.asUninitialized())
333317
or
334318
var.definedByReference(nodeFrom.asDefiningArgument())
319+
or
320+
var.definedPartiallyAt(nodeFrom.asPartialDefinition())
335321
) and
336322
varToExprStep(var, nodeTo.asExpr())
337323
)
338324
or
339325
// Expr -> DefinitionByReferenceNode
340326
exprToDefinitionByReferenceStep(nodeFrom.asExpr(), nodeTo.asDefiningArgument())
327+
or
328+
// `this` -> adjacent-`this`
329+
ThisFlow::adjacentThisRefs(nodeFrom, nodeTo)
330+
or
331+
// post-update-`this` -> following-`this`-ref
332+
ThisFlow::adjacentThisRefs(nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo)
341333
}
342334

343335
/**

0 commit comments

Comments
 (0)