@@ -271,7 +271,8 @@ module API {
271
271
this = Impl:: MkMethodAccessNode ( result ) or
272
272
this = Impl:: MkBackwardNode ( result , _) or
273
273
this = Impl:: MkForwardNode ( result , _) or
274
- this = Impl:: MkSinkNode ( result )
274
+ this = Impl:: MkSinkNode ( result ) or
275
+ this = Impl:: MkNamespaceOfTypeNameNode ( result )
275
276
}
276
277
277
278
/** Gets the location of this node. */
@@ -324,45 +325,6 @@ module API {
324
325
}
325
326
}
326
327
327
- /** A node representing a module/class object with epsilon edges to its descendents. */
328
- private class ModuleNode extends Node , Impl:: MkModule {
329
- string qualifiedModule ;
330
- int n ;
331
-
332
- ModuleNode ( ) { this = Impl:: MkModule ( qualifiedModule , n ) }
333
-
334
- ModuleNode getNext ( ) { result = Impl:: MkModule ( qualifiedModule , n + 1 ) }
335
-
336
- ModuleNode getPred ( ) { result .getNext ( ) = this }
337
-
338
- string getComponent ( ) { result = qualifiedModule .splitAt ( "." , n ) }
339
-
340
- string getModule ( ) {
341
- not exists ( this .getPred ( ) ) and
342
- result = this .getComponent ( )
343
- or
344
- result = this .getPred ( ) .getModule ( ) + "." + this .getComponent ( )
345
- }
346
-
347
- override string toString ( ) { result = "Module(" + this .getModule ( ) + ")" }
348
- }
349
-
350
- /** A node representing instances of a module/class with epsilon edges to its ancestors. */
351
- private class InstanceUp extends Node , Impl:: MkInstanceUp {
352
- /** Gets the module whose instances are represented by this API node. */
353
- string getType ( ) { this = Impl:: MkInstanceUp ( result ) }
354
-
355
- override string toString ( ) { result = "ModuleInstanceUp(" + this .getType ( ) + ")" }
356
- }
357
-
358
- /** A node representing instances of a module/class with epsilon edges to its descendents. */
359
- private class InstanceDownNode extends Node , Impl:: MkInstanceDown {
360
- /** Gets the module whose instances are represented by this API node. */
361
- string getType ( ) { this = Impl:: MkInstanceDown ( result ) }
362
-
363
- override string toString ( ) { result = "ModuleInstanceDown(" + this .getType ( ) + ")" }
364
- }
365
-
366
328
/** A node corresponding to the method being invoked at a method call. */
367
329
class MethodAccessNode extends Node , Impl:: MkMethodAccessNode {
368
330
override string toString ( ) { result = "MethodAccessNode(" + this .asCall ( ) + ")" }
@@ -378,6 +340,22 @@ module API {
378
340
override string toString ( ) { result = "SinkNode(" + this .getInducingNode ( ) + ")" }
379
341
}
380
342
343
+ private class UsingNode extends Node , Impl:: MkUsingNode {
344
+ UsingStmt using ; // TODO: This should really be the cfg node, I think
345
+
346
+ UsingNode ( ) { this = Impl:: MkUsingNode ( using ) }
347
+
348
+ override string toString ( ) { result = "UsingNode(" + using + ")" }
349
+ }
350
+
351
+ private class NamespaceOfTypeNameNode extends Node , Impl:: MkNamespaceOfTypeNameNode {
352
+ DataFlow:: QualifiedTypeNameNode typeName ;
353
+
354
+ NamespaceOfTypeNameNode ( ) { this = Impl:: MkNamespaceOfTypeNameNode ( typeName ) }
355
+
356
+ override string toString ( ) { result = "NamespaceOfTypeNameNode(" + typeName + ")" }
357
+ }
358
+
381
359
/**
382
360
* An API entry point.
383
361
*
@@ -415,11 +393,15 @@ module API {
415
393
/** Gets the root node. */
416
394
Node root ( ) { result instanceof RootNode }
417
395
418
- /**
419
- * Gets the node that represents the module with qualified
420
- * name `qualifiedModule`.
421
- */
422
- ModuleNode mod ( string qualifiedModule , int n ) { result = Impl:: MkModule ( qualifiedModule , n ) }
396
+ bindingset [ name]
397
+ pragma [ inline_late]
398
+ Node namespace ( string name ) {
399
+ // This predicate is currently not 'inline_late' because 'n' can be an input or output
400
+ Impl:: namespace ( name , result )
401
+ }
402
+
403
+ pragma [ inline]
404
+ Node getTopLevelMember ( string name ) { Impl:: topLevelMember ( name , result ) }
423
405
424
406
/**
425
407
* Gets an unqualified call at the top-level with the given method name.
@@ -466,44 +448,14 @@ module API {
466
448
467
449
cached
468
450
private module Impl {
469
- private predicate isGacModule ( string s ) {
470
- s =
471
- [
472
- "System.Management.Automation" ,
473
- "Microsoft.Management.Infrastructure" ,
474
- "Microsoft.PowerShell.Security" ,
475
- "Microsoft.PowerShell.Commands.Management" ,
476
- "Microsoft.PowerShell.Commands.Utility"
477
- ]
478
- }
479
-
480
- private predicate isModule ( string s , int n ) {
481
- (
482
- any ( UsingStmt using ) .getName ( ) = s
483
- or
484
- any ( Cmd cmd ) .getNamespaceQualifier ( ) = s
485
- or
486
- any ( TypeNameExpr tn ) .getName ( ) = s
487
- or
488
- any ( ModuleManifest manifest ) .getModuleName ( ) = s
489
- or
490
- isGacModule ( s )
491
- ) and
492
- exists ( s .splitAt ( "." , n ) )
493
- }
494
-
495
451
cached
496
452
newtype TApiNode =
497
453
/** The root of the API graph. */
498
454
MkRoot ( ) or
499
455
/** The method accessed at `call`, synthetically treated as a separate object. */
500
456
MkMethodAccessNode ( DataFlow:: CallNode call ) or
501
- MkModule ( string qualifiedModule , int n ) { isModule ( qualifiedModule , n ) } or
502
- /** Instances of `mod` with epsilon edges to its ancestors. */
503
- MkInstanceUp ( string qualifiedType ) { exists ( MkModule ( qualifiedType , _) ) } or
504
- /** Instances of `mod` with epsilon edges to its descendents, and to its upward node. */
505
- MkInstanceDown ( string qualifiedType ) { exists ( MkModule ( qualifiedType , _) ) } or
506
- /** Intermediate node for following forward data flow. */
457
+ MkUsingNode ( UsingStmt using ) or
458
+ MkNamespaceOfTypeNameNode ( DataFlow:: QualifiedTypeNameNode typeName ) or
507
459
MkForwardNode ( DataFlow:: LocalSourceNode node , TypeTracker t ) { isReachable ( node , t ) } or
508
460
/** Intermediate node for following backward data flow. */
509
461
MkBackwardNode ( DataFlow:: LocalSourceNode node , TypeTracker t ) { isReachable ( node , t ) } or
@@ -523,10 +475,30 @@ module API {
523
475
pragma [ inline_late]
524
476
private DataFlow:: Node getNodeFromExpr ( Expr e ) { result .asExpr ( ) .getExpr ( ) = e }
525
477
478
+ private import frameworks.data.ModelsAsData
479
+
480
+ cached
481
+ predicate namespace ( string name , Node node ) {
482
+ exists ( DataFlow:: QualifiedTypeNameNode typeName |
483
+ typeName .getNamespace ( ) = name and
484
+ node = MkNamespaceOfTypeNameNode ( typeName )
485
+ )
486
+ or
487
+ exists ( UsingStmt using |
488
+ using .getName ( ) .toLowerCase ( ) = name and
489
+ node = MkUsingNode ( using )
490
+ )
491
+ or
492
+ node = ModelOutput:: getATypeNode ( name )
493
+ }
494
+
495
+ cached
496
+ predicate topLevelMember ( string name , Node node ) { memberEdge ( root ( ) , name , node ) }
497
+
526
498
cached
527
499
predicate toplevelCall ( string name , Node node ) {
528
500
exists ( DataFlow:: CallNode call |
529
- call .asExpr ( ) .getExpr ( ) .getEnclosingScope ( ) instanceof TopLevel and
501
+ call .asExpr ( ) .getExpr ( ) .getEnclosingScope ( ) instanceof TopLevelScriptBlock and
530
502
call .getName ( ) = name and
531
503
node = MkMethodAccessNode ( call )
532
504
)
@@ -544,26 +516,25 @@ module API {
544
516
545
517
cached
546
518
predicate memberEdge ( Node pred , string name , Node succ ) {
547
- exists ( MemberExpr member | succ = getForwardStartNode ( getNodeFromExpr ( member ) ) |
548
- pred = getForwardEndNode ( getALocalSourceStrict ( getNodeFromExpr ( member .getQualifier ( ) ) ) ) and
549
- name = member .getMemberName ( )
519
+ exists ( StringConstExpr read |
520
+ succ = getForwardStartNode ( getNodeFromExpr ( read ) ) and
521
+ pred = MkRoot ( ) and
522
+ name = read .getValueString ( )
523
+ )
524
+ or
525
+ exists ( DataFlow:: QualifiedTypeNameNode typeName |
526
+ typeName .getName ( ) = name and
527
+ pred = MkNamespaceOfTypeNameNode ( typeName ) and
528
+ succ = getForwardStartNode ( typeName )
550
529
)
530
+ // or
531
+ // TODO: Handle getAMember when the predecessor is a MkUsingNode?
551
532
}
552
533
553
534
cached
554
535
predicate methodEdge ( Node pred , string name , Node succ ) {
555
536
exists ( DataFlow:: CallNode call | succ = MkMethodAccessNode ( call ) and name = call .getName ( ) |
556
537
pred = getForwardEndNode ( getALocalSourceStrict ( call .getQualifier ( ) ) )
557
- or
558
- exists ( string qualifiedModule , ModuleManifest manifest , int n |
559
- pred = mod ( qualifiedModule , n ) and
560
- not exists ( mod ( qualifiedModule , n + 1 ) ) and
561
- manifest .getModuleName ( ) = qualifiedModule
562
- |
563
- manifest .getACmdLetToExport ( ) = name
564
- or
565
- manifest .getAFunctionToExport ( ) = name
566
- )
567
538
)
568
539
}
569
540
@@ -657,24 +628,10 @@ module API {
657
628
658
629
cached
659
630
predicate instanceEdge ( Node pred , Node succ ) {
660
- exists ( string qualifiedType , int n |
661
- pred = MkModule ( qualifiedType , n ) and
662
- not exists ( MkModule ( qualifiedType , n + 1 ) )
663
- |
664
- exists ( DataFlow:: TypeNameNode typeName |
665
- typeName .getTypeName ( ) = qualifiedType and
666
- succ = getForwardStartNode ( typeName )
667
- )
668
- or
669
- exists ( DataFlow:: ObjectCreationNode objCreation |
670
- objCreation .getConstructedTypeName ( ) = qualifiedType and
671
- succ = getForwardStartNode ( objCreation )
672
- )
673
- or
674
- exists ( DataFlow:: ParameterNode p |
675
- p .getParameter ( ) .getStaticType ( ) = qualifiedType and
676
- succ = getForwardStartNode ( p )
677
- )
631
+ // TODO: Also model parameters with a given type here
632
+ exists ( DataFlow:: ObjectCreationNode objCreation |
633
+ pred = getForwardEndNode ( objCreation .getConstructedTypeNode ( ) ) and
634
+ succ = getForwardStartNode ( objCreation )
678
635
)
679
636
}
680
637
0 commit comments