2
2
* Provides modeling for Rack applications.
3
3
*/
4
4
5
+ private import codeql.ruby.AST
5
6
private import codeql.ruby.ApiGraphs
6
7
private import codeql.ruby.DataFlow
7
8
private import codeql.ruby.typetracking.TypeTracker
@@ -15,8 +16,18 @@ private class PotentialCallNode extends DataFlow::CallableNode {
15
16
PotentialCallNode ( ) {
16
17
this .getNumberOfParameters ( ) = 1 and
17
18
(
18
- this .( DataFlow:: MethodNode ) .getMethodName ( ) = "call" or
19
- not this instanceof DataFlow:: MethodNode
19
+ this .( DataFlow:: MethodNode ) .getMethodName ( ) = "call"
20
+ or
21
+ not this instanceof DataFlow:: MethodNode and
22
+ exists ( DataFlow:: CallNode cn | cn .getMethodName ( ) = "run" |
23
+ this .( DataFlow:: LocalSourceNode ) .flowsTo ( cn .getArgument ( 0 ) )
24
+ or
25
+ // TODO: `Proc.new` should automatically propagate flow from its block argument
26
+ any ( DataFlow:: CallNode proc |
27
+ proc = API:: getTopLevelMember ( "Proc" ) .getAnInstantiation ( ) and
28
+ proc .getBlock ( ) = this
29
+ ) .( DataFlow:: LocalSourceNode ) .flowsTo ( cn .getArgument ( 0 ) )
30
+ )
20
31
)
21
32
}
22
33
}
@@ -33,14 +44,14 @@ private class CallNode extends PotentialCallNode {
33
44
RP:: PotentialResponseNode getResponse ( ) { result = resp }
34
45
}
35
46
36
- private DataFlow:: LocalSourceNode trackRackResponse ( TypeBackTracker t , DataFlow :: CallableNode call ) {
47
+ private DataFlow:: LocalSourceNode trackRackResponse ( TypeBackTracker t , PotentialCallNode call ) {
37
48
t .start ( ) and
38
49
result = call .getAReturnNode ( ) .getALocalSource ( )
39
50
or
40
51
exists ( TypeBackTracker t2 | result = trackRackResponse ( t2 , call ) .backtrack ( t2 , t ) )
41
52
}
42
53
43
- private RP:: PotentialResponseNode trackRackResponse ( DataFlow :: CallableNode call ) {
54
+ private RP:: PotentialResponseNode trackRackResponse ( PotentialCallNode call ) {
44
55
result = trackRackResponse ( TypeBackTracker:: end ( ) , call )
45
56
}
46
57
0 commit comments