File tree 1 file changed +30
-0
lines changed
javascript/ql/src/Security/CWE-730
1 file changed +30
-0
lines changed Original file line number Diff line number Diff line change @@ -56,6 +56,36 @@ class PromiseExecutor extends AsyncTerminatableFunction {
56
56
override string getKind ( ) { result = "promise" }
57
57
}
58
58
59
+ /**
60
+ * A callback-invoking function heuristic as a function that can be terminated in an asynchronous context.
61
+ */
62
+ class FunctionWithCallback extends AsyncTerminatableFunction {
63
+ DataFlow:: ParameterNode callbackParameter ;
64
+
65
+ FunctionWithCallback ( ) {
66
+ // the last parameter is the callback
67
+ callbackParameter = this .getLastParameter ( ) and
68
+ // simple escape analysis
69
+ not exists ( DataFlow:: Node escape | callbackParameter .flowsTo ( escape ) |
70
+ escape = any ( DataFlow:: PropWrite w ) .getRhs ( ) or
71
+ escape = any ( DataFlow:: CallNode c ) .getAnArgument ( )
72
+ ) and
73
+ // no return value
74
+ ( this .getFunction ( ) instanceof ArrowFunctionExpr or not exists ( this .getAReturn ( ) ) ) and
75
+ // all callback invocations are terminal (note that this permits calls in closures)
76
+ forex ( DataFlow:: CallNode termination | termination = callbackParameter .getACall ( ) |
77
+ termination .asExpr ( ) = any ( Function f ) .getExit ( ) .getAPredecessor ( )
78
+ ) and
79
+ // avoid confusion with promises
80
+ not this instanceof PromiseExecutor and
81
+ not exists ( PromiseCandidate c | this .flowsTo ( c .getAnArgument ( ) ) )
82
+ }
83
+
84
+ override DataFlow:: CallNode getTermination ( ) { result = callbackParameter .getACall ( ) }
85
+
86
+ override string getKind ( ) { result = "asynchronous function" }
87
+ }
88
+
59
89
/**
60
90
* A data stream.
61
91
*/
You can’t perform that action at this time.
0 commit comments