@@ -112,6 +112,33 @@ class FlowSummaryIntermediateAwaitStoreNode extends DataFlow::Node,
112
112
}
113
113
}
114
114
115
+ predicate mentionsExceptionalReturn ( FlowSummaryImpl:: Public:: SummarizedCallable callable ) {
116
+ exists ( FlowSummaryImpl:: Private:: SummaryNode node | node .getSummarizedCallable ( ) = callable |
117
+ FlowSummaryImpl:: Private:: summaryReturnNode ( node , MkExceptionalReturnKind ( ) )
118
+ or
119
+ FlowSummaryImpl:: Private:: summaryOutNode ( _, node , MkExceptionalReturnKind ( ) )
120
+ )
121
+ }
122
+
123
+ /**
124
+ * Exceptional return node in a summarized callable whose summary does not mention `ReturnValue[exception]`.
125
+ *
126
+ * By default, every call inside such a callable will forward their exceptional return to the caller's
127
+ * exceptional return, i.e. exceptions are not caught.
128
+ */
129
+ class FlowSummaryDefaultExceptionalReturn extends DataFlow:: Node ,
130
+ TFlowSummaryDefaultExceptionalReturn
131
+ {
132
+ private FlowSummaryImpl:: Public:: SummarizedCallable callable ;
133
+
134
+ FlowSummaryDefaultExceptionalReturn ( ) { this = TFlowSummaryDefaultExceptionalReturn ( callable ) }
135
+
136
+ FlowSummaryImpl:: Public:: SummarizedCallable getSummarizedCallable ( ) { result = callable }
137
+
138
+ cached
139
+ override string toString ( ) { result = "[default exceptional return] " + callable }
140
+ }
141
+
115
142
class CaptureNode extends DataFlow:: Node , TSynthCaptureNode {
116
143
/** Gets the underlying node from the variable-capture library. */
117
144
VariableCaptureOutput:: SynthesizedCaptureNode getNode ( ) {
@@ -296,6 +323,9 @@ private predicate returnNodeImpl(DataFlow::Node node, ReturnKind kind) {
296
323
)
297
324
or
298
325
FlowSummaryImpl:: Private:: summaryReturnNode ( node .( FlowSummaryNode ) .getSummaryNode ( ) , kind )
326
+ or
327
+ node instanceof FlowSummaryDefaultExceptionalReturn and
328
+ kind = MkExceptionalReturnKind ( )
299
329
}
300
330
301
331
private DataFlow:: Node getAnOutNodeImpl ( DataFlowCall call , ReturnKind kind ) {
@@ -311,6 +341,10 @@ private DataFlow::Node getAnOutNodeImpl(DataFlowCall call, ReturnKind kind) {
311
341
or
312
342
FlowSummaryImpl:: Private:: summaryOutNode ( call .( SummaryCall ) .getReceiver ( ) ,
313
343
result .( FlowSummaryNode ) .getSummaryNode ( ) , kind )
344
+ or
345
+ kind = MkExceptionalReturnKind ( ) and
346
+ result .( FlowSummaryDefaultExceptionalReturn ) .getSummarizedCallable ( ) =
347
+ call .( SummaryCall ) .getSummarizedCallable ( )
314
348
}
315
349
316
350
class ReturnNode extends DataFlow:: Node {
@@ -404,6 +438,19 @@ abstract class LibraryCallable extends string {
404
438
DataFlow:: InvokeNode getACallSimple ( ) { none ( ) }
405
439
}
406
440
441
+ /** Internal subclass of `LibraryCallable`, whose member predicates should not be visible on `SummarizedCallable`. */
442
+ abstract class LibraryCallableInternal extends LibraryCallable {
443
+ bindingset [ this ]
444
+ LibraryCallableInternal ( ) { any ( ) }
445
+
446
+ /**
447
+ * Gets a call to this library callable.
448
+ *
449
+ * Same as `getACall()` but is evaluated later and may depend negatively on `getACall()`.
450
+ */
451
+ DataFlow:: InvokeNode getACallStage2 ( ) { none ( ) }
452
+ }
453
+
407
454
private predicate isParameterNodeImpl ( Node p , DataFlowCallable c , ParameterPosition pos ) {
408
455
exists ( Parameter parameter |
409
456
parameter = c .asSourceCallable ( ) .( Function ) .getParameter ( pos .asPositional ( ) ) and
@@ -505,6 +552,8 @@ DataFlowCallable nodeGetEnclosingCallable(Node node) {
505
552
or
506
553
result .asLibraryCallable ( ) = node .( FlowSummaryIntermediateAwaitStoreNode ) .getSummarizedCallable ( )
507
554
or
555
+ result .asLibraryCallable ( ) = node .( FlowSummaryDefaultExceptionalReturn ) .getSummarizedCallable ( )
556
+ or
508
557
node = TGenericSynthesizedNode ( _, _, result )
509
558
}
510
559
@@ -865,6 +914,8 @@ class SummaryCall extends DataFlowCall, MkSummaryCall {
865
914
866
915
/** Gets the receiver node. */
867
916
FlowSummaryImpl:: Private:: SummaryNode getReceiver ( ) { result = receiver }
917
+
918
+ FlowSummaryImpl:: Public:: SummarizedCallable getSummarizedCallable ( ) { result = enclosingCallable }
868
919
}
869
920
870
921
/**
@@ -976,7 +1027,11 @@ DataFlowCallable viableCallable(DataFlowCall node) {
976
1027
or
977
1028
exists ( LibraryCallable callable |
978
1029
result = MkLibraryCallable ( callable ) and
979
- node .asOrdinaryCall ( ) = [ callable .getACall ( ) , callable .getACallSimple ( ) ]
1030
+ node .asOrdinaryCall ( ) =
1031
+ [
1032
+ callable .getACall ( ) , callable .getACallSimple ( ) ,
1033
+ callable .( LibraryCallableInternal ) .getACallStage2 ( )
1034
+ ]
980
1035
)
981
1036
or
982
1037
result .asSourceCallableNotExterns ( ) = node .asImpliedLambdaCall ( )
@@ -1217,14 +1272,29 @@ predicate simpleLocalFlowStep(Node node1, Node node2) {
1217
1272
1218
1273
predicate localMustFlowStep ( Node node1 , Node node2 ) { node1 = node2 .getImmediatePredecessor ( ) }
1219
1274
1275
+ /**
1276
+ * Holds if `node1 -> node2` should be removed as a jump step.
1277
+ *
1278
+ * Currently this is done as a workaround for the local steps generated from IIFEs.
1279
+ */
1280
+ private predicate excludedJumpStep ( Node node1 , Node node2 ) {
1281
+ exists ( ImmediatelyInvokedFunctionExpr iife |
1282
+ iife .argumentPassing ( node2 .asExpr ( ) , node1 .asExpr ( ) )
1283
+ or
1284
+ node1 = iife .getAReturnedExpr ( ) .flow ( ) and
1285
+ node2 = iife .getInvocation ( ) .flow ( )
1286
+ )
1287
+ }
1288
+
1220
1289
/**
1221
1290
* Holds if data can flow from `node1` to `node2` through a non-local step
1222
1291
* that does not follow a call edge. For example, a step through a global
1223
1292
* variable.
1224
1293
*/
1225
1294
predicate jumpStep ( Node node1 , Node node2 ) {
1226
1295
valuePreservingStep ( node1 , node2 ) and
1227
- node1 .getContainer ( ) != node2 .getContainer ( )
1296
+ node1 .getContainer ( ) != node2 .getContainer ( ) and
1297
+ not excludedJumpStep ( node1 , node2 )
1228
1298
or
1229
1299
FlowSummaryPrivate:: Steps:: summaryJumpStep ( node1 .( FlowSummaryNode ) .getSummaryNode ( ) ,
1230
1300
node2 .( FlowSummaryNode ) .getSummaryNode ( ) )
0 commit comments