@@ -10,6 +10,7 @@ private import semmle.code.powershell.dataflow.DataFlow
10
10
private import semmle.code.powershell.typetracking.ApiGraphShared
11
11
private import semmle.code.powershell.typetracking.internal.TypeTrackingImpl
12
12
private import semmle.code.powershell.controlflow.Cfg
13
+ private import frameworks.data.internal.ApiGraphModels
13
14
private import frameworks.data.internal.ApiGraphModelsExtensions as Extensions
14
15
private import frameworks.data.internal.ApiGraphModelsSpecific as Specific
15
16
private import semmle.code.powershell.dataflow.internal.DataFlowPrivate as DataFlowPrivate
@@ -262,8 +263,7 @@ module API {
262
263
this = Impl:: MkMethodAccessNode ( result ) or
263
264
this = Impl:: MkBackwardNode ( result , _) or
264
265
this = Impl:: MkForwardNode ( result , _) or
265
- this = Impl:: MkSinkNode ( result ) or
266
- this = Impl:: MkNamespaceOfTypeNameNode ( result )
266
+ this = Impl:: MkSinkNode ( result )
267
267
}
268
268
269
269
/** Gets the location of this node. */
@@ -272,6 +272,10 @@ module API {
272
272
or
273
273
this instanceof RootNode and
274
274
result instanceof EmptyLocation
275
+ or
276
+ not this instanceof RootNode and
277
+ not exists ( this .getInducingNode ( ) ) and
278
+ result instanceof EmptyLocation
275
279
}
276
280
277
281
/**
@@ -331,20 +335,84 @@ module API {
331
335
override string toString ( ) { result = "SinkNode(" + this .getInducingNode ( ) + ")" }
332
336
}
333
337
334
- private class UsingNode extends Node , Impl:: MkUsingNode {
335
- UsingStmt using ; // TODO: This should really be the cfg node, I think
338
+ abstract private class AbstractTypeNameNode extends Node {
339
+ string prefix ;
340
+
341
+ bindingset [ prefix]
342
+ AbstractTypeNameNode ( ) { any ( ) }
343
+
344
+ override string toString ( ) { result = "TypeNameNode(" + this .getTypeName ( ) + ")" }
345
+
346
+ string getComponent ( ) {
347
+ exists ( int n |
348
+ result = prefix .splitAt ( "." , n ) and
349
+ not exists ( prefix .splitAt ( "." , n + 1 ) )
350
+ )
351
+ }
352
+
353
+ string getTypeName ( ) { result = prefix }
354
+
355
+ abstract Node getSuccessor ( string name ) ;
356
+
357
+ Node memberEdge ( string name ) { none ( ) }
358
+
359
+ Node methodEdge ( string name ) { none ( ) }
360
+
361
+ final predicate isImplicit ( ) { not this .isExplicit ( _) }
362
+
363
+ predicate isExplicit ( DataFlow:: TypeNameNode typeName ) { none ( ) }
364
+ }
365
+
366
+ final class TypeNameNode = AbstractTypeNameNode ;
367
+
368
+ private class ExplicitTypeNameNode extends AbstractTypeNameNode , Impl:: MkExplicitTypeNameNode {
369
+ ExplicitTypeNameNode ( ) { this = Impl:: MkExplicitTypeNameNode ( prefix ) }
370
+
371
+ final override Node getSuccessor ( string name ) {
372
+ exists ( ExplicitTypeNameNode succ |
373
+ succ = Impl:: MkExplicitTypeNameNode ( prefix + "." + name ) and
374
+ result = succ
375
+ )
376
+ or
377
+ exists ( DataFlow:: TypeNameNode typeName , int n , string lowerCaseName |
378
+ Specific:: needsExplicitTypeNameNode ( typeName , prefix ) and
379
+ lowerCaseName = typeName .getLowerCaseName ( ) and
380
+ name = lowerCaseName .splitAt ( "." , n ) and
381
+ not lowerCaseName .matches ( "%.%" ) and
382
+ result = getForwardStartNode ( typeName )
383
+ )
384
+ }
385
+
386
+ final override predicate isExplicit ( DataFlow:: TypeNameNode typeName ) {
387
+ Specific:: needsExplicitTypeNameNode ( typeName , prefix )
388
+ }
389
+ }
336
390
337
- UsingNode ( ) { this = Impl :: MkUsingNode ( using ) }
391
+ private string getAnAlias ( string cmdlet ) { Specific :: aliasModel ( cmdlet , result ) }
338
392
339
- override string toString ( ) { result = "UsingNode(" + using + ")" }
393
+ predicate implicitCmdlet ( string mod , string cmdlet ) {
394
+ exists ( string cmdlet0 |
395
+ Specific:: cmdletModel ( mod , cmdlet0 ) and
396
+ cmdlet = [ cmdlet0 , getAnAlias ( cmdlet0 ) ]
397
+ )
340
398
}
341
399
342
- private class NamespaceOfTypeNameNode extends Node , Impl:: MkNamespaceOfTypeNameNode {
343
- DataFlow:: QualifiedTypeNameNode typeName ;
400
+ private class ImplicitTypeNameNode extends AbstractTypeNameNode , Impl:: MkImplicitTypeNameNode {
401
+ ImplicitTypeNameNode ( ) { this = Impl:: MkImplicitTypeNameNode ( prefix ) }
402
+
403
+ final override Node getSuccessor ( string name ) {
404
+ result = Impl:: MkImplicitTypeNameNode ( prefix + "." + name )
405
+ }
344
406
345
- NamespaceOfTypeNameNode ( ) { this = Impl :: MkNamespaceOfTypeNameNode ( typeName ) }
407
+ final override Node memberEdge ( string name ) { result = this . methodEdge ( name ) }
346
408
347
- override string toString ( ) { result = "NamespaceOfTypeNameNode(" + typeName + ")" }
409
+ final override Node methodEdge ( string name ) {
410
+ exists ( DataFlow:: CallNode call |
411
+ result = Impl:: MkMethodAccessNode ( call ) and
412
+ name = call .getLowerCaseName ( ) and
413
+ implicitCmdlet ( prefix , name )
414
+ )
415
+ }
348
416
}
349
417
350
418
/**
@@ -438,8 +506,8 @@ module API {
438
506
MkRoot ( ) or
439
507
/** The method accessed at `call`, synthetically treated as a separate object. */
440
508
MkMethodAccessNode ( DataFlow:: CallNode call ) or
441
- MkUsingNode ( UsingStmt using ) or
442
- MkNamespaceOfTypeNameNode ( DataFlow :: QualifiedTypeNameNode typeName ) or
509
+ MkExplicitTypeNameNode ( string prefix ) { Specific :: needsExplicitTypeNameNode ( _ , prefix ) } or
510
+ MkImplicitTypeNameNode ( string prefix ) { Specific :: needsImplicitTypeNameNode ( prefix ) } or
443
511
MkForwardNode ( DataFlow:: LocalSourceNode node , TypeTracker t ) { isReachable ( node , t ) } or
444
512
/** Intermediate node for following backward data flow. */
445
513
MkBackwardNode ( DataFlow:: LocalSourceNode node , TypeTracker t ) { isReachable ( node , t ) } or
@@ -455,27 +523,8 @@ module API {
455
523
node = any ( EntryPoint e ) .getASink ( )
456
524
}
457
525
458
- bindingset [ e]
459
- pragma [ inline_late]
460
- private DataFlow:: Node getNodeFromExpr ( Expr e ) { result .asExpr ( ) .getExpr ( ) = e }
461
-
462
526
private import frameworks.data.ModelsAsData
463
527
464
- cached
465
- predicate namespace ( string name , Node node ) {
466
- exists ( DataFlow:: QualifiedTypeNameNode typeName |
467
- typeName .getNamespace ( ) = name and
468
- node = MkNamespaceOfTypeNameNode ( typeName )
469
- )
470
- or
471
- exists ( UsingStmt using |
472
- using .getName ( ) .toLowerCase ( ) = name and
473
- node = MkUsingNode ( using )
474
- )
475
- or
476
- node = ModelOutput:: getATypeNode ( name )
477
- }
478
-
479
528
cached
480
529
predicate topLevelMember ( string name , Node node ) { memberEdge ( root ( ) , name , node ) }
481
530
@@ -492,42 +541,51 @@ module API {
492
541
predicate memberEdge ( Node pred , string name , Node succ ) {
493
542
pred = API:: root ( ) and
494
543
(
495
- exists ( StringConstExpr read |
496
- succ = getForwardStartNode ( getNodeFromExpr ( read ) ) and
497
- name = read .getValueString ( )
498
- )
544
+ succ .( TypeNameNode ) .getTypeName ( ) = name
499
545
or
500
546
exists ( DataFlow:: AutomaticVariableNode automatic |
501
547
automatic .getLowerCaseName ( ) = name and
502
548
succ = getForwardStartNode ( automatic )
503
549
)
504
- or
505
- succ = getAnImplicitRootMember ( name )
506
550
)
507
551
or
508
- exists ( DataFlow :: QualifiedTypeNameNode typeName |
509
- typeName .getLowerCaseName ( ) = name and
510
- pred = MkNamespaceOfTypeNameNode ( typeName ) and
511
- succ = getForwardStartNode ( typeName )
552
+ exists ( TypeNameNode typeName | pred = typeName |
553
+ typeName .getSuccessor ( name ) = succ
554
+ or
555
+ typeName . memberEdge ( name ) = succ
512
556
)
513
557
or
514
- exists ( MemberExprReadAccess read |
515
- read .getLowerCaseMemberName ( ) .toLowerCase ( ) = name and
516
- pred = getForwardEndNode ( getALocalSourceStrict ( getNodeFromExpr ( read .getQualifier ( ) ) ) ) and
517
- succ = getForwardStartNode ( getNodeFromExpr ( read ) )
558
+ exists ( DataFlow:: Node qualifier | pred = getForwardEndNode ( getALocalSourceStrict ( qualifier ) ) |
559
+ exists ( CfgNodes:: ExprNodes:: MemberExprReadAccessCfgNode read |
560
+ read .getQualifier ( ) = qualifier .asExpr ( ) and
561
+ read .getLowerCaseMemberName ( ) = name and
562
+ succ = getForwardStartNode ( DataFlow:: exprNode ( read ) )
563
+ )
564
+ or
565
+ exists ( DataFlow:: CallNode call |
566
+ call .getLowerCaseName ( ) = name and
567
+ call .getQualifier ( ) = qualifier and
568
+ succ = MkMethodAccessNode ( call )
569
+ )
518
570
)
519
571
}
520
572
521
573
cached
522
574
predicate methodEdge ( Node pred , string name , Node succ ) {
523
575
exists ( DataFlow:: CallNode call |
524
- succ = MkMethodAccessNode ( call ) and name = call . getLowerCaseName ( )
525
- |
576
+ succ = MkMethodAccessNode ( call ) and
577
+ name = call . getLowerCaseName ( ) and
526
578
pred = getForwardEndNode ( getALocalSourceStrict ( call .getQualifier ( ) ) )
527
579
)
528
580
or
581
+ pred .( TypeNameNode ) .methodEdge ( name ) = succ
582
+ or
529
583
pred = API:: root ( ) and
530
- succ = getAnImplicitRootMember ( name )
584
+ exists ( DataFlow:: CallNode call |
585
+ not exists ( call .getQualifier ( ) ) and
586
+ succ = MkMethodAccessNode ( call ) and
587
+ name = call .getLowerCaseName ( )
588
+ )
531
589
}
532
590
533
591
cached
0 commit comments