@@ -25,56 +25,75 @@ private predicate gemFileStep(Gem::GemSpec gem, Folder folder, int n) {
2525}
2626
2727/**
28- * A callable method or accessor from either the Ruby Standard Library, a 3rd party library, or from the source .
28+ * Gets the namespace of an endpoint in `file` .
2929 */
30- class Endpoint extends DataFlow:: MethodNode {
31- Endpoint ( ) { this .isPublic ( ) and not isUninteresting ( this ) }
30+ string getNamespace ( File file ) {
31+ exists ( Folder folder | folder = file .getParentContainer ( ) |
32+ // The nearest gemspec to this endpoint, if one exists
33+ result = min ( Gem:: GemSpec g , int n | gemFileStep ( g , folder , n ) | g order by n ) .getName ( )
34+ or
35+ not gemFileStep ( _, folder , _) and
36+ result = ""
37+ )
38+ }
3239
33- File getFile ( ) { result = this .getLocation ( ) .getFile ( ) }
40+ abstract class Endpoint instanceof DataFlow:: Node {
41+ string getNamespace ( ) { result = getNamespace ( super .getLocation ( ) .getFile ( ) ) }
3442
35- string getName ( ) { result = this . getMethodName ( ) }
43+ string getFileName ( ) { result = super . getLocation ( ) . getFile ( ) . getBaseName ( ) }
3644
37- /**
38- * Gets the namespace of this endpoint.
39- */
40- bindingset [ this ]
41- string getNamespace ( ) {
42- exists ( Folder folder | folder = this .getFile ( ) .getParentContainer ( ) |
43- // The nearest gemspec to this endpoint, if one exists
44- result = min ( Gem:: GemSpec g , int n | gemFileStep ( g , folder , n ) | g order by n ) .getName ( )
45- or
46- not gemFileStep ( _, folder , _) and
47- result = ""
48- )
45+ string toString ( ) { result = super .toString ( ) }
46+
47+ Location getLocation ( ) { result = super .getLocation ( ) }
48+
49+ abstract string getType ( ) ;
50+
51+ abstract string getName ( ) ;
52+
53+ abstract string getParameters ( ) ;
54+
55+ abstract boolean getSupportedStatus ( ) ;
56+
57+ abstract string getSupportedType ( ) ;
58+ }
59+
60+ /**
61+ * A callable method or accessor from source code.
62+ */
63+ class MethodEndpoint extends Endpoint instanceof DataFlow:: MethodNode {
64+ MethodEndpoint ( ) {
65+ this .isPublic ( ) and
66+ not isUninteresting ( this )
4967 }
5068
69+ DataFlow:: MethodNode getNode ( ) { result = this }
70+
71+ override string getName ( ) { result = super .getMethodName ( ) }
72+
5173 /**
5274 * Gets the unbound type name of this endpoint.
5375 */
54- bindingset [ this ]
55- string getTypeName ( ) {
76+ override string getType ( ) {
5677 result =
57- any ( DataFlow:: ModuleNode m | m .getOwnInstanceMethod ( this .getMethodName ( ) ) = this )
58- .getQualifiedName ( ) or
78+ any ( DataFlow:: ModuleNode m | m .getOwnInstanceMethod ( this .getName ( ) ) = this ) .getQualifiedName ( ) or
5979 result =
60- any ( DataFlow:: ModuleNode m | m .getOwnSingletonMethod ( this .getMethodName ( ) ) = this )
80+ any ( DataFlow:: ModuleNode m | m .getOwnSingletonMethod ( this .getName ( ) ) = this )
6181 .getQualifiedName ( ) + "!"
6282 }
6383
6484 /**
6585 * Gets the parameter types of this endpoint.
6686 */
67- bindingset [ this ]
68- string getParameterTypes ( ) {
69- // For now, return the names of postional and keyword parameters. We don't always have type information, so we can't return type names.
87+ override string getParameters ( ) {
88+ // For now, return the names of positional and keyword parameters. We don't always have type information, so we can't return type names.
7089 // We don't yet handle splat params or block params.
7190 result =
7291 "(" +
7392 concat ( string key , string value |
74- value = any ( int i | i .toString ( ) = key | this .asCallable ( ) .getParameter ( i ) ) .getName ( )
93+ value = any ( int i | i .toString ( ) = key | super .asCallable ( ) .getParameter ( i ) ) .getName ( )
7594 or
7695 exists ( DataFlow:: ParameterNode param |
77- param = this .asCallable ( ) .getKeywordParameter ( key )
96+ param = super .asCallable ( ) .getKeywordParameter ( key )
7897 |
7998 value = key + ":"
8099 )
@@ -89,11 +108,11 @@ class Endpoint extends DataFlow::MethodNode {
89108
90109 /** Holds if this API is a known source. */
91110 pragma [ nomagic]
92- abstract predicate isSource ( ) ;
111+ predicate isSource ( ) { this . getNode ( ) instanceof SourceCallable }
93112
94113 /** Holds if this API is a known sink. */
95114 pragma [ nomagic]
96- abstract predicate isSink ( ) ;
115+ predicate isSink ( ) { this . getNode ( ) instanceof SinkCallable }
97116
98117 /** Holds if this API is a known neutral. */
99118 pragma [ nomagic]
@@ -107,9 +126,11 @@ class Endpoint extends DataFlow::MethodNode {
107126 this .hasSummary ( ) or this .isSource ( ) or this .isSink ( ) or this .isNeutral ( )
108127 }
109128
110- boolean getSupportedStatus ( ) { if this .isSupported ( ) then result = true else result = false }
129+ override boolean getSupportedStatus ( ) {
130+ if this .isSupported ( ) then result = true else result = false
131+ }
111132
112- string getSupportedType ( ) {
133+ override string getSupportedType ( ) {
113134 this .isSink ( ) and result = "sink"
114135 or
115136 this .isSource ( ) and result = "source"
@@ -131,7 +152,7 @@ string methodClassification(Call method) {
131152
132153class TestFile extends File {
133154 TestFile ( ) {
134- this .getRelativePath ( ) .regexpMatch ( ".*(test|spec).+" ) and
155+ this .getRelativePath ( ) .regexpMatch ( ".*(test|spec|examples ).+" ) and
135156 not this .getAbsolutePath ( ) .matches ( "%/ql/test/%" ) // allows our test cases to work
136157 }
137158}
@@ -163,10 +184,32 @@ class SourceCallable extends DataFlow::CallableNode {
163184}
164185
165186/**
166- * A class of effectively public callables from source code.
187+ * A module defined in source code
167188 */
168- class PublicEndpointFromSource extends Endpoint {
169- override predicate isSource ( ) { this instanceof SourceCallable }
189+ class ModuleEndpoint extends Endpoint {
190+ private DataFlow:: ModuleNode moduleNode ;
191+
192+ ModuleEndpoint ( ) {
193+ this =
194+ min ( DataFlow:: Node n , Location loc |
195+ n .asExpr ( ) .getExpr ( ) = moduleNode .getADeclaration ( ) and
196+ loc = n .getLocation ( )
197+ |
198+ n order by loc .getFile ( ) .getAbsolutePath ( ) , loc .getStartLine ( ) , loc .getStartColumn ( )
199+ ) and
200+ not moduleNode .( Module ) .isBuiltin ( ) and
201+ not moduleNode .getLocation ( ) .getFile ( ) instanceof TestFile
202+ }
203+
204+ DataFlow:: ModuleNode getNode ( ) { result = moduleNode }
205+
206+ override string getType ( ) { result = this .getNode ( ) .getQualifiedName ( ) }
207+
208+ override string getName ( ) { result = "" }
209+
210+ override string getParameters ( ) { result = "" }
211+
212+ override boolean getSupportedStatus ( ) { result = false }
170213
171- override predicate isSink ( ) { this instanceof SinkCallable }
214+ override string getSupportedType ( ) { result = "" }
172215}
0 commit comments