@@ -11,6 +11,61 @@ private import semmle.code.csharp.dispatch.Dispatch
1111private import semmle.code.csharp.frameworks.EntityFramework
1212private import semmle.code.csharp.frameworks.NHibernate
1313
14+ /** Calculation of the relative order in which `this` references are read. */
15+ private module ThisFlow {
16+ class BasicBlock = ControlFlow:: BasicBlock ;
17+
18+ /** Holds if `n` is a `this` access at control flow node `cfn`. */
19+ private predicate thisAccess ( Node n , ControlFlow:: Node cfn ) {
20+ n .( InstanceParameterNode ) .getCallable ( ) = cfn .( ControlFlow:: Nodes:: EntryNode ) .getCallable ( )
21+ or
22+ n .asExprAtNode ( cfn ) = any ( Expr e | e instanceof ThisAccess or e instanceof BaseAccess )
23+ }
24+
25+ private predicate thisAccess ( Node n , BasicBlock bb , int i ) { thisAccess ( n , bb .getNode ( i ) ) }
26+
27+ private predicate thisRank ( Node n , BasicBlock bb , int rankix ) {
28+ exists ( int i |
29+ i = rank [ rankix ] ( int j | thisAccess ( _, bb , j ) ) and
30+ thisAccess ( n , bb , i )
31+ )
32+ }
33+
34+ private int lastRank ( BasicBlock bb ) { result = max ( int rankix | thisRank ( _, bb , rankix ) ) }
35+
36+ private predicate blockPrecedesThisAccess ( BasicBlock bb ) { thisAccess ( _, bb .getASuccessor * ( ) , _) }
37+
38+ private predicate thisAccessBlockReaches ( BasicBlock bb1 , BasicBlock bb2 ) {
39+ thisAccess ( _, bb1 , _) and bb2 = bb1 .getASuccessor ( )
40+ or
41+ exists ( BasicBlock mid |
42+ thisAccessBlockReaches ( bb1 , mid ) and
43+ bb2 = mid .getASuccessor ( ) and
44+ not thisAccess ( _, mid , _) and
45+ blockPrecedesThisAccess ( bb2 )
46+ )
47+ }
48+
49+ private predicate thisAccessBlockStep ( BasicBlock bb1 , BasicBlock bb2 ) {
50+ thisAccessBlockReaches ( bb1 , bb2 ) and
51+ thisAccess ( _, bb2 , _)
52+ }
53+
54+ /** Holds if `n1` and `n2` are control-flow adjacent references to `this`. */
55+ predicate adjacentThisRefs ( Node n1 , Node n2 ) {
56+ exists ( int rankix , BasicBlock bb |
57+ thisRank ( n1 , bb , rankix ) and
58+ thisRank ( n2 , bb , rankix + 1 )
59+ )
60+ or
61+ exists ( BasicBlock bb1 , BasicBlock bb2 |
62+ thisRank ( n1 , bb1 , lastRank ( bb1 ) ) and
63+ thisAccessBlockStep ( bb1 , bb2 ) and
64+ thisRank ( n2 , bb2 , 1 )
65+ )
66+ }
67+ }
68+
1469/** Provides predicates related to local data flow. */
1570module LocalFlow {
1671 class LocalExprStepConfiguration extends ControlFlowReachabilityConfiguration {
@@ -183,6 +238,7 @@ module DataFlowPrivateCached {
183238 TExprNode ( ControlFlow:: Nodes:: ElementNode cfn ) { cfn .getElement ( ) instanceof Expr } or
184239 TCilExprNode ( CIL:: Expr e ) { e .getImplementation ( ) instanceof CIL:: BestImplementation } or
185240 TSsaDefinitionNode ( Ssa:: Definition def ) or
241+ TInstanceParameterNode ( Callable c ) { c .hasBody ( ) and not c .( Modifiable ) .isStatic ( ) } or
186242 TCilParameterNode ( CIL:: Parameter p ) { p .getMethod ( ) .hasBody ( ) } or
187243 TTaintedParameterNode ( Parameter p ) { p .getCallable ( ) .hasBody ( ) } or
188244 TTaintedReturnNode ( ControlFlow:: Nodes:: ElementNode cfn ) {
@@ -198,14 +254,17 @@ module DataFlowPrivateCached {
198254 ) {
199255 cfn .getElement ( ) instanceof DelegateArgumentToLibraryCallable and
200256 any ( DelegateArgumentConfiguration x ) .hasExprPath ( _, cfn , _, call )
201- }
257+ } or
258+ TMallocNode ( ControlFlow:: Nodes:: ElementNode cfn ) { cfn .getElement ( ) instanceof ObjectCreation }
202259
203260 cached
204261 DotNet:: Callable getEnclosingCallable ( Node node ) {
205262 result = node .( ExprNode ) .getExpr ( ) .getEnclosingCallable ( )
206263 or
207264 result = node .( SsaDefinitionNode ) .getDefinition ( ) .getEnclosingCallable ( )
208265 or
266+ node = TInstanceParameterNode ( result )
267+ or
209268 exists ( CIL:: Parameter p | node = TCilParameterNode ( p ) | result = p .getCallable ( ) )
210269 or
211270 result = getEnclosingCallable ( node .( TaintedParameterNode ) .getUnderlyingNode ( ) )
@@ -219,6 +278,10 @@ module DataFlowPrivateCached {
219278 exists ( ControlFlow:: Nodes:: ElementNode cfn | node = TImplicitDelegateOutNode ( cfn , _) |
220279 result = cfn .getEnclosingCallable ( )
221280 )
281+ or
282+ exists ( ControlFlow:: Nodes:: ElementNode cfn | node = TMallocNode ( cfn ) |
283+ result = cfn .getEnclosingCallable ( )
284+ )
222285 }
223286
224287 cached
@@ -227,6 +290,8 @@ module DataFlowPrivateCached {
227290 or
228291 result = node .( SsaDefinitionNode ) .getDefinition ( ) .getSourceVariable ( ) .getType ( )
229292 or
293+ exists ( Callable c | node = TInstanceParameterNode ( c ) | result = c .getDeclaringType ( ) )
294+ or
230295 exists ( CIL:: Parameter p | node = TCilParameterNode ( p ) | result = p .getType ( ) )
231296 or
232297 result = getType ( node .( TaintedParameterNode ) .getUnderlyingNode ( ) )
@@ -238,6 +303,10 @@ module DataFlowPrivateCached {
238303 exists ( ControlFlow:: Nodes:: ElementNode cfn | node = TImplicitDelegateOutNode ( cfn , _) |
239304 result = cfn .getElement ( ) .( Expr ) .getType ( )
240305 )
306+ or
307+ exists ( ControlFlow:: Nodes:: ElementNode cfn | node = TMallocNode ( cfn ) |
308+ result = cfn .getElement ( ) .( Expr ) .getType ( )
309+ )
241310 }
242311
243312 cached
@@ -246,6 +315,8 @@ module DataFlowPrivateCached {
246315 or
247316 result = node .( SsaDefinitionNode ) .getDefinition ( ) .getLocation ( )
248317 or
318+ exists ( Callable c | node = TInstanceParameterNode ( c ) | result = c .getLocation ( ) )
319+ or
249320 exists ( CIL:: Parameter p | node = TCilParameterNode ( p ) | result = p .getLocation ( ) )
250321 or
251322 result = getLocation ( node .( TaintedParameterNode ) .getUnderlyingNode ( ) )
@@ -259,6 +330,10 @@ module DataFlowPrivateCached {
259330 exists ( ControlFlow:: Nodes:: ElementNode cfn | node = TImplicitDelegateOutNode ( cfn , _) |
260331 result = cfn .getLocation ( )
261332 )
333+ or
334+ exists ( ControlFlow:: Nodes:: ElementNode cfn | node = TMallocNode ( cfn ) |
335+ result = cfn .getLocation ( )
336+ )
262337 }
263338
264339 cached
@@ -275,6 +350,8 @@ module DataFlowPrivateCached {
275350 result = def .toString ( )
276351 )
277352 or
353+ node = TInstanceParameterNode ( _) and result = "this"
354+ or
278355 exists ( CIL:: Parameter p | node = TCilParameterNode ( p ) | result = p .toString ( ) )
279356 or
280357 result = toString ( node .( TaintedParameterNode ) .getUnderlyingNode ( ) )
@@ -288,6 +365,8 @@ module DataFlowPrivateCached {
288365 exists ( ControlFlow:: Nodes:: ElementNode cfn | node = TImplicitDelegateOutNode ( cfn , _) |
289366 result = "[output] " + cfn
290367 )
368+ or
369+ node = TMallocNode ( _) and result = "malloc"
291370 }
292371
293372 /**
@@ -313,6 +392,8 @@ module DataFlowPrivateCached {
313392 nodeTo = TExprNode ( cfnTo )
314393 )
315394 or
395+ ThisFlow:: adjacentThisRefs ( nodeFrom , nodeTo )
396+ or
316397 // Flow into SSA pseudo definition
317398 exists ( Ssa:: Definition def , Ssa:: PseudoDefinition pseudo |
318399 LocalFlow:: localFlowSsaInput ( nodeFrom , def )
@@ -390,6 +471,18 @@ private module ParameterNodes {
390471 override predicate isParameterOf ( DotNet:: Callable c , int i ) { c .getParameter ( i ) = parameter }
391472 }
392473
474+ /** An implicit instance (`this`) parameter. */
475+ class InstanceParameterNode extends ParameterNode , TInstanceParameterNode {
476+ private Callable callable ;
477+
478+ InstanceParameterNode ( ) { this = TInstanceParameterNode ( callable ) }
479+
480+ /** Gets the callable containing this implicit instance parameter. */
481+ Callable getCallable ( ) { result = callable }
482+
483+ override predicate isParameterOf ( DotNet:: Callable c , int pos ) { callable = c and pos = - 1 }
484+ }
485+
393486 /**
394487 * A tainted parameter. Tainted parameters are a mere implementation detail, used
395488 * to restrict tainted flow into callables to just taint tracking (just like flow
@@ -539,7 +632,11 @@ private module ArgumentNodes {
539632 }
540633
541634 private DotNet:: Expr getArgument ( DotNet:: Expr call , int i ) {
542- call = any ( DispatchCall dc | result = dc .getArgument ( i ) ) .getCall ( )
635+ call = any ( DispatchCall dc |
636+ result = dc .getArgument ( i )
637+ or
638+ result = dc .getQualifier ( ) and i = - 1 and not dc .getAStaticTarget ( ) .( Modifiable ) .isStatic ( )
639+ ) .getCall ( )
543640 or
544641 result = call .( DelegateCall ) .getArgument ( i )
545642 or
@@ -650,6 +747,23 @@ private module ArgumentNodes {
650747 )
651748 }
652749 }
750+
751+ /**
752+ * A node that corresponds to the value of an object creation (`new C()`) before
753+ * the constructor has run.
754+ */
755+ class MallocNode extends ArgumentNode , TMallocNode {
756+ private ControlFlow:: Nodes:: ElementNode cfn ;
757+
758+ MallocNode ( ) { this = TMallocNode ( cfn ) }
759+
760+ override predicate argumentOf ( DataFlowCall call , int pos ) {
761+ call = TNonDelegateCall ( cfn , _) and
762+ pos = - 1
763+ }
764+
765+ override ControlFlow:: Node getControlFlowNode ( ) { result = cfn }
766+ }
653767}
654768import ArgumentNodes
655769
0 commit comments