@@ -56,7 +56,7 @@ private string getTokenFeature(DataFlow::Node endpoint, string featureName) {
5656 result =
5757 concat ( API:: Node node , string accessPath |
5858 node .getInducingNode ( ) .( DataFlow:: CallNode ) .getAnArgument ( ) = endpoint and
59- accessPath = AccessPaths:: getAccessPath ( node , includeStructuralInfo )
59+ AccessPaths:: accessPaths ( node , includeStructuralInfo , accessPath , _ )
6060 |
6161 accessPath , " "
6262 )
@@ -102,7 +102,7 @@ private string getACallBasedTokenFeatureComponent(
102102 //
103103 // would have a callee API name of `mongoose`.
104104 featureName = "calleeApiName" and
105- result = getAnApiName ( call )
105+ exists ( API :: Node apiNode | AccessPaths :: accessPaths ( apiNode , false , _ , result ) and call = apiNode . getInducingNode ( ) )
106106 )
107107}
108108
@@ -145,16 +145,6 @@ module FunctionBodies {
145145 }
146146}
147147
148- /**
149- * Returns a name of the API that a node originates from, if the node originates from an API.
150- *
151- * This predicate may have multiple results if the node corresponds to multiple nodes in the API graph forest.
152- */
153- pragma [ inline]
154- private string getAnApiName ( DataFlow:: Node node ) {
155- API:: moduleImport ( result ) .getASuccessor * ( ) .getInducingNode ( ) = node
156- }
157-
158148/**
159149 * This module provides functionality for getting a representation of the access path of nodes
160150 * within the program.
@@ -200,65 +190,66 @@ private module AccessPaths {
200190 }
201191
202192 /** Get the access path for the node. This includes structural information like `member`, `param`, and `functionalarg` if `includeStructuralInfo` is true. */
203- string getAccessPath ( API:: Node node , Boolean includeStructuralInfo ) {
204- node = API:: moduleImport ( result )
193+ predicate accessPaths ( API:: Node node , Boolean includeStructuralInfo , string accessPath , string apiName ) {
194+ //node = API::moduleImport(result)
195+ node = API:: moduleImport ( apiName ) and accessPath = apiName
205196 or
206- exists ( API:: Node base , string baseName |
207- base .getDepth ( ) < node .getDepth ( ) and baseName = getAccessPath ( base , includeStructuralInfo )
197+ exists ( API:: Node previousNode , string previousAccessPath |
198+ previousNode .getDepth ( ) < node .getDepth ( ) and accessPaths ( previousNode , includeStructuralInfo , previousAccessPath , apiName )
208199 |
209200 // e.g. `new X`, `X()`
210- node = [ base .getInstance ( ) , base .getReturn ( ) ] and
201+ node = [ previousNode .getInstance ( ) , previousNode .getReturn ( ) ] and
211202 if includeStructuralInfo = true
212- then result = baseName + " instanceorreturn"
213- else result = baseName
203+ then accessPath = previousAccessPath + " instanceorreturn"
204+ else accessPath = previousAccessPath
214205 or
215206 // e.g. `x.y`, `x[y]`, `const { y } = x`, where `y` is non-numeric and is known at analysis
216207 // time.
217208 exists ( string member |
218- node = base .getMember ( member ) and
219- not node = base .getUnknownMember ( ) and
209+ node = previousNode .getMember ( member ) and
210+ not node = previousNode .getUnknownMember ( ) and
220211 not isNumericString ( member ) and
221- not ( member = "default" and base = API:: moduleImport ( _) ) and
212+ not ( member = "default" and previousNode = API:: moduleImport ( _) ) and
222213 not member = "then" // use the 'promised' edges for .then callbacks
223214 |
224215 if includeStructuralInfo = true
225- then result = baseName + " member " + member
226- else result = baseName + " " + member
216+ then accessPath = previousAccessPath + " member " + member
217+ else accessPath = previousAccessPath + " " + member
227218 )
228219 or
229220 // e.g. `x.y`, `x[y]`, `const { y } = x`, where `y` is numeric or not known at analysis time.
230221 (
231- node = base .getUnknownMember ( ) or
232- node = base .getMember ( any ( string s | isNumericString ( s ) ) )
222+ node = previousNode .getUnknownMember ( ) or
223+ node = previousNode .getMember ( any ( string s | isNumericString ( s ) ) )
233224 ) and
234- if includeStructuralInfo = true then result = baseName + " member" else result = baseName
225+ if includeStructuralInfo = true then accessPath = previousAccessPath + " member" else accessPath = previousAccessPath
235226 or
236227 // e.g. `x.then(y => ...)`
237- node = base .getPromised ( ) and
238- result = baseName
228+ node = previousNode .getPromised ( ) and
229+ accessPath = previousAccessPath
239230 or
240231 // e.g. `x.y((a, b) => ...)`
241232 // Name callback parameters after their name in the source code.
242233 // For example, the `res` parameter in `express.get('/foo', (req, res) => {...})` will be
243234 // named `express member get functionalarg param res`.
244235 exists ( string paramName |
245- node = getNamedParameter ( base .getAParameter ( ) , paramName ) and
236+ node = getNamedParameter ( previousNode .getAParameter ( ) , paramName ) and
246237 (
247238 if includeStructuralInfo = true
248- then result = baseName + " functionalarg param " + paramName
249- else result = baseName + " " + paramName
239+ then accessPath = previousAccessPath + " functionalarg param " + paramName
240+ else accessPath = previousAccessPath + " " + paramName
250241 )
251242 or
252243 exists ( string callbackName , string index |
253244 node =
254- getNamedParameter ( base .getASuccessor ( "param " + index ) .getMember ( callbackName ) ,
245+ getNamedParameter ( previousNode .getASuccessor ( "param " + index ) .getMember ( callbackName ) ,
255246 paramName ) and
256247 index != "-1" and // ignore receiver
257248 if includeStructuralInfo = true
258249 then
259- result =
260- baseName + " functionalarg " + index + " " + callbackName + " param " + paramName
261- else result = baseName + " " + index + " " + callbackName + " " + paramName
250+ accessPath =
251+ previousAccessPath + " functionalarg " + index + " " + callbackName + " param " + paramName
252+ else accessPath = previousAccessPath + " " + index + " " + callbackName + " " + paramName
262253 )
263254 )
264255 )
0 commit comments