@@ -56,7 +56,12 @@ private module Cached {
56
56
} or
57
57
TFlowSummaryNode ( FlowSummaryImpl:: Private:: SummaryNode sn ) or
58
58
TFieldValueNode ( Field f ) or
59
- TCaptureNode ( CaptureFlow:: SynthesizedCaptureNode cn )
59
+ TCaptureNode ( CaptureFlow:: SynthesizedCaptureNode cn ) or
60
+ TExceptionOutNode ( Call call ) or
61
+ TExceptionReturnNode ( Callable callable ) or
62
+ TCatchTypeTestNode ( CatchClause catch ) or
63
+ TCatchParameterNode ( CatchClause catch ) or
64
+ TUncaughtNode ( TryStmt try ) { ExceptionFlow:: tryCatch ( try , _) }
60
65
61
66
cached
62
67
newtype TContent =
@@ -133,6 +138,16 @@ module Public {
133
138
result = this .( CaptureNode ) .getTypeImpl ( )
134
139
or
135
140
result = this .( FieldValueNode ) .getField ( ) .getType ( )
141
+ or
142
+ result instanceof TypeThrowable and this instanceof ExceptionOutNode
143
+ or
144
+ result instanceof TypeThrowable and this instanceof ExceptionReturnNode
145
+ or
146
+ result instanceof TypeThrowable and this instanceof CatchTypeTestNode
147
+ or
148
+ result = this .( CatchParameterNode ) .getVariable ( ) .getType ( )
149
+ or
150
+ result instanceof TypeThrowable and this instanceof UncaughtNode
136
151
}
137
152
138
153
/** Gets the callable in which this node occurs. */
@@ -335,6 +350,27 @@ module Public {
335
350
/** Holds if this is an access to an object's own instance. */
336
351
predicate isOwnInstanceAccess ( ) { this .getInstanceAccess ( ) .isOwnInstanceAccess ( ) }
337
352
}
353
+
354
+ /**
355
+ * A node representing a thrown exception as the result of a call.
356
+ */
357
+ class ExceptionOutNode extends Node , TExceptionOutNode {
358
+ override string toString ( ) { result = "Exception out: " + this .getCall ( ) .toString ( ) }
359
+
360
+ override Location getLocation ( ) { result = this .getCall ( ) .getLocation ( ) }
361
+
362
+ /** Gets the associated call. */
363
+ Call getCall ( ) { this = TExceptionOutNode ( result ) }
364
+ }
365
+
366
+ /**
367
+ * A node representing a thrown exception being returned from a callable.
368
+ */
369
+ class ExceptionReturnNode extends Node , TExceptionReturnNode {
370
+ override string toString ( ) { result = "Exception return" }
371
+
372
+ override Location getLocation ( ) { result = this .getEnclosingCallable ( ) .getLocation ( ) }
373
+ }
338
374
}
339
375
340
376
private import Public
@@ -378,7 +414,12 @@ module Private {
378
414
result = nodeGetEnclosingCallable ( n .( ImplicitPostUpdateNode ) .getPreUpdateNode ( ) ) or
379
415
result .asSummarizedCallable ( ) = n .( FlowSummaryNode ) .getSummarizedCallable ( ) or
380
416
result .asCallable ( ) = n .( CaptureNode ) .getSynthesizedCaptureNode ( ) .getEnclosingCallable ( ) or
381
- result .asFieldScope ( ) = n .( FieldValueNode ) .getField ( )
417
+ result .asFieldScope ( ) = n .( FieldValueNode ) .getField ( ) or
418
+ result .asCallable ( ) = n .( ExceptionOutNode ) .getCall ( ) .getEnclosingCallable ( ) or
419
+ n = TExceptionReturnNode ( result .asCallable ( ) ) or
420
+ result .asCallable ( ) = n .( CatchTypeTestNode ) .getCatch ( ) .getEnclosingCallable ( ) or
421
+ result .asCallable ( ) = n .( CatchParameterNode ) .getCatch ( ) .getEnclosingCallable ( ) or
422
+ result .asCallable ( ) = n .( UncaughtNode ) .getTry ( ) .getEnclosingCallable ( )
382
423
}
383
424
384
425
/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */
@@ -429,15 +470,23 @@ module Private {
429
470
DataFlowCall getCall ( ) { this .argumentOf ( result , _) }
430
471
}
431
472
432
- /** A data flow node that occurs as the result of a `ReturnStmt`. */
473
+ /**
474
+ * A data flow node that occurs as the result of a `ReturnStmt` or an
475
+ * exception being returned.
476
+ */
433
477
class ReturnNode extends Node {
434
478
ReturnNode ( ) {
435
479
exists ( ReturnStmt ret | this .asExpr ( ) = ret .getResult ( ) ) or
436
- this .( FlowSummaryNode ) .isReturn ( )
480
+ this .( FlowSummaryNode ) .isReturn ( ) or
481
+ this instanceof ExceptionReturnNode
437
482
}
438
483
439
484
/** Gets the kind of this returned value. */
440
- ReturnKind getKind ( ) { any ( ) }
485
+ ReturnKind getKind ( ) {
486
+ if this instanceof ExceptionReturnNode
487
+ then result instanceof ExceptionReturnKind
488
+ else result instanceof NormalReturnKind
489
+ }
441
490
}
442
491
443
492
/** A data flow node that represents the output of a call. */
@@ -446,13 +495,24 @@ module Private {
446
495
this .asExpr ( ) instanceof MethodAccess
447
496
or
448
497
this .( FlowSummaryNode ) .isOut ( _)
498
+ or
499
+ this instanceof ExceptionOutNode
449
500
}
450
501
451
502
/** Gets the underlying call. */
452
503
DataFlowCall getCall ( ) {
453
504
result .asCall ( ) = this .asExpr ( )
454
505
or
455
506
this .( FlowSummaryNode ) .isOut ( result )
507
+ or
508
+ result .asCall ( ) = this .( ExceptionOutNode ) .getCall ( )
509
+ }
510
+
511
+ /** Gets the kind of this returned value. */
512
+ ReturnKind getKind ( ) {
513
+ if this instanceof ExceptionOutNode
514
+ then result instanceof ExceptionReturnKind
515
+ else result instanceof NormalReturnKind
456
516
}
457
517
}
458
518
@@ -519,6 +579,66 @@ module Private {
519
579
cn .isInstanceAccess ( ) and result = cn .getEnclosingCallable ( ) .getDeclaringType ( )
520
580
}
521
581
}
582
+
583
+ /**
584
+ * A data flow node that carries an exception and tests if it is caught in a
585
+ * given catch clause.
586
+ */
587
+ class CatchTypeTestNode extends Node , TCatchTypeTestNode {
588
+ override string toString ( ) { result = this .getCatch ( ) .toString ( ) }
589
+
590
+ override Location getLocation ( ) { result = this .getCatch ( ) .getLocation ( ) }
591
+
592
+ /** Gets the catch clause associated with this node. */
593
+ CatchClause getCatch ( ) { this = TCatchTypeTestNode ( result ) }
594
+
595
+ Node getSuccessor ( boolean match ) {
596
+ match = true and
597
+ this .getCatch ( ) = result .( CatchParameterNode ) .getCatch ( )
598
+ or
599
+ match = false and
600
+ exists ( TryStmt try , int i , CatchClause cc |
601
+ cc = this .getCatch ( ) and
602
+ cc = try .getCatchClause ( i ) and
603
+ // A catch-all does not allow for uncaught exceptions.
604
+ not cc .getACaughtType ( ) instanceof TypeThrowable
605
+ |
606
+ result .( CatchTypeTestNode ) .getCatch ( ) = try .getCatchClause ( i + 1 )
607
+ or
608
+ not exists ( try .getCatchClause ( i + 1 ) ) and
609
+ result .( UncaughtNode ) .getTry ( ) = try
610
+ )
611
+ }
612
+ }
613
+
614
+ /**
615
+ * A data flow node that holds the value of a variable defined in a catch
616
+ * clause.
617
+ */
618
+ class CatchParameterNode extends Node , TCatchParameterNode {
619
+ override string toString ( ) { result = this .getVariable ( ) .toString ( ) }
620
+
621
+ override Location getLocation ( ) { result = this .getVariable ( ) .getLocation ( ) }
622
+
623
+ /** Gets the catch clause associated with this node. */
624
+ CatchClause getCatch ( ) { this = TCatchParameterNode ( result ) }
625
+
626
+ /** Gets the variable declaration associated with this node. */
627
+ LocalVariableDeclExpr getVariable ( ) { result = this .getCatch ( ) .getVariable ( ) }
628
+ }
629
+
630
+ /**
631
+ * A data flow node that carries an exception that is uncaught by a try-catch
632
+ * statement.
633
+ */
634
+ class UncaughtNode extends Node , TUncaughtNode {
635
+ override string toString ( ) { result = "Uncaught exception" }
636
+
637
+ override Location getLocation ( ) { result = this .getTry ( ) .getLocation ( ) }
638
+
639
+ /** Gets the try statement associated with this node. */
640
+ TryStmt getTry ( ) { this = TUncaughtNode ( result ) }
641
+ }
522
642
}
523
643
524
644
private import Private
0 commit comments