@@ -114,13 +114,13 @@ module API {
114114 * Gets a node such that there is an edge in the API graph between this node and the other
115115 * one, and that edge is labeled with `lbl`.
116116 */
117- Node getASuccessor ( string lbl ) { Impl:: edge ( this , lbl , result ) }
117+ Node getASuccessor ( Label :: ApiLabel lbl ) { Impl:: edge ( this , lbl , result ) }
118118
119119 /**
120120 * Gets a node such that there is an edge in the API graph between that other node and
121121 * this one, and that edge is labeled with `lbl`
122122 */
123- Node getAPredecessor ( string lbl ) { this = result .getASuccessor ( lbl ) }
123+ Node getAPredecessor ( Label :: ApiLabel lbl ) { this = result .getASuccessor ( lbl ) }
124124
125125 /**
126126 * Gets a node such that there is an edge in the API graph between this node and the other
@@ -174,9 +174,8 @@ module API {
174174 length = 0 and
175175 result = ""
176176 or
177- exists ( Node pred , string lbl , string predpath |
177+ exists ( Node pred , Label :: ApiLabel lbl , string predpath |
178178 Impl:: edge ( pred , lbl , this ) and
179- lbl != "" and
180179 predpath = pred .getAPath ( length - 1 ) and
181180 exists ( string dot | if length = 1 then dot = "" else dot = "." |
182181 result = predpath + dot + lbl and
@@ -335,7 +334,8 @@ module API {
335334 *
336335 * For instance, `prefix_member("foo.bar", "baz", "foo.bar.baz")` would hold.
337336 */
338- private predicate prefix_member ( TApiNode base , string member , TApiNode sub ) {
337+ cached
338+ predicate prefix_member ( TApiNode base , string member , TApiNode sub ) {
339339 exists ( string sub_str , string regexp |
340340 regexp = "(.+)[.]([^.]+)" and
341341 base = MkModuleImport ( sub_str .regexpCapture ( regexp , 1 ) ) and
@@ -386,7 +386,7 @@ module API {
386386 * `lbl` in the API graph.
387387 */
388388 cached
389- predicate use ( TApiNode base , string lbl , DataFlow:: Node ref ) {
389+ predicate use ( TApiNode base , Label :: ApiLabel lbl , DataFlow:: Node ref ) {
390390 exists ( DataFlow:: LocalSourceNode src , DataFlow:: LocalSourceNode pred |
391391 // First, we find a predecessor of the node `ref` that we want to determine. The predecessor
392392 // is any node that is a type-tracked use of a data flow node (`src`), which is itself a
@@ -481,7 +481,7 @@ module API {
481481 * Holds if there is an edge from `pred` to `succ` in the API graph that is labeled with `lbl`.
482482 */
483483 cached
484- predicate edge ( TApiNode pred , string lbl , TApiNode succ ) {
484+ predicate edge ( TApiNode pred , Label :: ApiLabel lbl , TApiNode succ ) {
485485 /* There's an edge from the root node for each imported module. */
486486 exists ( string m |
487487 pred = MkRoot ( ) and
@@ -514,36 +514,126 @@ module API {
514514 cached
515515 int distanceFromRoot ( TApiNode nd ) = shortestDistances( MkRoot / 0 , edge / 2 ) ( _, nd , result )
516516 }
517- }
518517
519- private module Label {
520- /** Gets the edge label for the module `m`. */
521- bindingset [ m]
522- bindingset [ result ]
523- string mod ( string m ) { result = "moduleImport(\"" + m + "\")" }
524-
525- /** Gets the `member` edge label for member `m`. */
526- bindingset [ m]
527- bindingset [ result ]
528- string member ( string m ) { result = "getMember(\"" + m + "\")" }
529-
530- /** Gets the `member` edge label for the unknown member. */
531- string unknownMember ( ) { result = "getUnknownMember()" }
532-
533- /** Gets the `member` edge label for the given attribute reference. */
534- string memberFromRef ( DataFlow:: AttrRef pr ) {
535- result = member ( pr .getAttributeName ( ) )
536- or
537- not exists ( pr .getAttributeName ( ) ) and
538- result = unknownMember ( )
539- }
518+ /** Provides classes modeling the various edges (labels) in the API graph. */
519+ module Label {
520+ /** A label in the API-graph */
521+ class ApiLabel extends TLabel {
522+ /** Gets a string representation of this label. */
523+ string toString ( ) { result = "???" }
524+ }
525+
526+ private import LabelImpl
527+
528+ private module LabelImpl {
529+ private import semmle.python.dataflow.new.internal.Builtins
530+ private import semmle.python.dataflow.new.internal.ImportStar
531+
532+ newtype TLabel =
533+ MkLabelModule ( string mod ) { exists ( Impl:: MkModuleImport ( mod ) ) } or
534+ MkLabelMember ( string member ) {
535+ member = any ( DataFlow:: AttrRef pr ) .getAttributeName ( ) or
536+ exists ( Builtins:: likelyBuiltin ( member ) ) or
537+ ImportStar:: namePossiblyDefinedInImportStar ( _, member , _) or
538+ Impl:: prefix_member ( _, member , _)
539+ } or
540+ MkLabelUnknownMember ( ) or
541+ MkLabelParameter ( int i ) {
542+ none ( ) // TODO: Fill in when adding def nodes
543+ } or
544+ MkLabelReturn ( ) or
545+ MkLabelSubclass ( ) or
546+ MkLabelAwait ( )
547+
548+ /** A label for a module. */
549+ class LabelModule extends ApiLabel {
550+ string mod ;
551+
552+ LabelModule ( ) { this = MkLabelModule ( mod ) }
553+
554+ /** Gets the module associated with this label. */
555+ string getMod ( ) { result = mod }
556+
557+ override string toString ( ) { result = "moduleImport(\"" + mod + "\")" }
558+ }
559+
560+ /** A label for the member named `prop`. */
561+ class LabelMember extends ApiLabel {
562+ string member ;
563+
564+ LabelMember ( ) { this = MkLabelMember ( member ) }
565+
566+ /** Gets the property associated with this label. */
567+ string getMember ( ) { result = member }
568+
569+ override string toString ( ) { result = "getMember(\"" + member + "\")" }
570+ }
571+
572+ /** A label for a member with an unknown name. */
573+ class LabelUnknownMember extends ApiLabel {
574+ LabelUnknownMember ( ) { this = MkLabelUnknownMember ( ) }
575+
576+ override string toString ( ) { result = "getUnknownMember()" }
577+ }
578+
579+ /** A label for parameter `i`. */
580+ class LabelParameter extends ApiLabel {
581+ int i ;
540582
541- /** Gets the `return` edge label. */
542- string return ( ) { result = "getReturn()" }
583+ LabelParameter ( ) { this = MkLabelParameter ( i ) }
543584
544- /** Gets the `subclass` edge label. */
545- string subclass ( ) { result = "getASubclass()" }
585+ override string toString ( ) { result = "getParameter(" + i + ")" }
546586
547- /** Gets the `await` edge label. */
548- string await ( ) { result = "getAwaited()" }
587+ /** Gets the index of the parameter for this label. */
588+ int getIndex ( ) { result = i }
589+ }
590+
591+ /** A label that gets the return value of a function. */
592+ class LabelReturn extends ApiLabel {
593+ LabelReturn ( ) { this = MkLabelReturn ( ) }
594+
595+ override string toString ( ) { result = "getReturn()" }
596+ }
597+
598+ /** A label that gets the subclass of a class. */
599+ class LabelSubclass extends ApiLabel {
600+ LabelSubclass ( ) { this = MkLabelSubclass ( ) }
601+
602+ override string toString ( ) { result = "getASubclass()" }
603+ }
604+
605+ /** A label for awaited values. */
606+ class LabelAwait extends ApiLabel {
607+ LabelAwait ( ) { this = MkLabelAwait ( ) }
608+
609+ override string toString ( ) { result = "getAwaited()" }
610+ }
611+ }
612+
613+ /** Gets the edge label for the module `m`. */
614+ LabelModule mod ( string m ) { result .getMod ( ) = m }
615+
616+ /** Gets the `member` edge label for member `m`. */
617+ LabelMember member ( string m ) { result .getMember ( ) = m }
618+
619+ /** Gets the `member` edge label for the unknown member. */
620+ LabelUnknownMember unknownMember ( ) { any ( ) }
621+
622+ /** Gets the `member` edge label for the given attribute reference. */
623+ ApiLabel memberFromRef ( DataFlow:: AttrRef pr ) {
624+ result = member ( pr .getAttributeName ( ) )
625+ or
626+ not exists ( pr .getAttributeName ( ) ) and
627+ result = unknownMember ( )
628+ }
629+
630+ /** Gets the `return` edge label. */
631+ LabelReturn return ( ) { any ( ) }
632+
633+ /** Gets the `subclass` edge label. */
634+ LabelSubclass subclass ( ) { any ( ) }
635+
636+ /** Gets the `await` edge label. */
637+ LabelAwait await ( ) { any ( ) }
638+ }
549639}
0 commit comments