@@ -6,57 +6,12 @@ private import cpp
66private import semmle.code.cpp.dataflow.internal.FlowVar
77private 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-
479cached
4810private 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 */
314261UninitializedNode 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