@@ -29,11 +29,12 @@ private predicate deadcode(Expr e) {
2929module SsaFlow {
3030 module Impl = SsaImpl:: DataFlowIntegration;
3131
32- private predicate ssaDefAssigns ( SsaExplicitWrite def , Expr value ) {
32+ private predicate ssaDefAssigns ( SsaExplicitWrite def , Node value ) {
3333 exists ( VariableUpdate upd | upd = def .getDefiningExpr ( ) |
34- value = upd .( VariableAssign ) .getSource ( ) or
35- value = upd .( AssignOp ) or
36- value = upd .( RecordBindingVariableExpr )
34+ value .asExpr ( ) = upd .( VariableAssign ) .getSource ( ) or
35+ value .asExpr ( ) = upd .( AssignOp ) or
36+ value .asExpr ( ) = upd .( RecordBindingVariableExpr ) or
37+ value .( CatchParameterNode ) .getVariable ( ) = upd
3738 )
3839 }
3940
@@ -49,7 +50,7 @@ module SsaFlow {
4950 result .( Impl:: WriteDefSourceNode ) .getDefinition ( ) .( SsaParameterInit ) .getParameter ( ) = p
5051 )
5152 or
52- ssaDefAssigns ( result .( Impl:: WriteDefSourceNode ) .getDefinition ( ) , n . asExpr ( ) )
53+ ssaDefAssigns ( result .( Impl:: WriteDefSourceNode ) .getDefinition ( ) , n )
5354 }
5455
5556 predicate localFlowStep ( SsaSourceVariable v , Node nodeFrom , Node nodeTo , boolean isUseStep ) {
@@ -99,6 +100,11 @@ private module Cached {
99100 TFlowSummaryNode ( FlowSummaryImpl:: Private:: SummaryNode sn ) or
100101 TFieldValueNode ( Field f ) or
101102 TCaptureNode ( CaptureFlow:: SynthesizedCaptureNode cn ) or
103+ TExceptionOutNode ( DataFlowCall call ) or
104+ TExceptionReturnNode ( DataFlowCallable callable ) or
105+ TCatchTypeTestNode ( CatchClause catch ) or
106+ TCatchParameterNode ( CatchClause catch ) or
107+ TUncaughtNode ( TryStmt try ) { ExceptionFlow:: tryCatch ( try , _) } or
102108 TAdditionalNode ( Expr e , string id ) { any ( AdditionalDataFlowNode adfn ) .nodeAt ( e , id ) }
103109
104110 cached
@@ -177,6 +183,14 @@ module Public {
177183 or
178184 result = this .( FieldValueNode ) .getField ( ) .getType ( )
179185 or
186+ result instanceof TypeException and this instanceof ExceptionOutNode
187+ or
188+ result instanceof TypeException and this instanceof CatchTypeTestNode
189+ or
190+ result = this .( CatchParameterNode ) .getVariable ( ) .getType ( )
191+ or
192+ result instanceof TypeException and this instanceof UncaughtNode
193+ or
180194 result instanceof TypeObject and this instanceof AdditionalNode
181195 or
182196 result = this .( SsaNode ) .getTypeImpl ( )
@@ -383,6 +397,27 @@ module Public {
383397 predicate isOwnInstanceAccess ( ) { this .getInstanceAccess ( ) .isOwnInstanceAccess ( ) }
384398 }
385399
400+ /**
401+ * A node representing a thrown exception as the result of a call.
402+ */
403+ class ExceptionOutNode extends Node , TExceptionOutNode {
404+ override string toString ( ) { result = "Exception out: " + this .getCall ( ) .toString ( ) }
405+
406+ override Location getLocation ( ) { result = this .getCall ( ) .getLocation ( ) }
407+
408+ /** Gets the associated call. */
409+ DataFlowCall getCall ( ) { this = TExceptionOutNode ( result ) }
410+ }
411+
412+ /**
413+ * A node representing a thrown exception being returned from a callable.
414+ */
415+ class ExceptionReturnNode extends Node , TExceptionReturnNode {
416+ override string toString ( ) { result = "Exception return" }
417+
418+ override Location getLocation ( ) { result = this .getEnclosingCallable ( ) .getLocation ( ) }
419+ }
420+
386421 /** A node introduced by an extension of `AdditionalDataFlowNode`. */
387422 class AdditionalNode extends Node , TAdditionalNode {
388423 Expr e_ ;
@@ -455,6 +490,11 @@ module Private {
455490 result .asSummarizedCallable ( ) = n .( FlowSummaryNode ) .getSummarizedCallable ( ) or
456491 result .asCallable ( ) = n .( CaptureNode ) .getSynthesizedCaptureNode ( ) .getEnclosingCallable ( ) or
457492 result .asFieldScope ( ) = n .( FieldValueNode ) .getField ( ) or
493+ result = n .( ExceptionOutNode ) .getCall ( ) .getEnclosingCallable ( ) or
494+ n = TExceptionReturnNode ( result ) or
495+ result .asCallable ( ) = n .( CatchTypeTestNode ) .getCatch ( ) .getEnclosingCallable ( ) or
496+ result .asCallable ( ) = n .( CatchParameterNode ) .getCatch ( ) .getEnclosingCallable ( ) or
497+ result .asCallable ( ) = n .( UncaughtNode ) .getTry ( ) .getEnclosingCallable ( ) or
458498 result .asCallable ( ) = any ( Expr e | n .( AdditionalNode ) .nodeAt ( e , _) ) .getEnclosingCallable ( ) or
459499 result .asCallable ( ) = n .( SsaNode ) .getBasicBlock ( ) .getEnclosingCallable ( )
460500 }
@@ -507,15 +547,23 @@ module Private {
507547 DataFlowCall getCall ( ) { this .argumentOf ( result , _) }
508548 }
509549
510- /** A data flow node that occurs as the result of a `ReturnStmt`. */
550+ /**
551+ * A data flow node that occurs as the result of a `ReturnStmt` or an
552+ * exception being returned.
553+ */
511554 class ReturnNode extends Node {
512555 ReturnNode ( ) {
513556 exists ( ReturnStmt ret | this .asExpr ( ) = ret .getResult ( ) ) or
514- this .( FlowSummaryNode ) .isReturn ( )
557+ this .( FlowSummaryNode ) .isReturn ( ) or
558+ this instanceof ExceptionReturnNode
515559 }
516560
517561 /** Gets the kind of this returned value. */
518- ReturnKind getKind ( ) { any ( ) }
562+ ReturnKind getKind ( ) {
563+ if this instanceof ExceptionReturnNode
564+ then result instanceof ExceptionReturnKind
565+ else result instanceof NormalReturnKind
566+ }
519567 }
520568
521569 /** A data flow node that represents the output of a call. */
@@ -524,13 +572,24 @@ module Private {
524572 this .asExpr ( ) instanceof MethodCall
525573 or
526574 this .( FlowSummaryNode ) .isOut ( _)
575+ or
576+ this instanceof ExceptionOutNode
527577 }
528578
529579 /** Gets the underlying call. */
530580 DataFlowCall getCall ( ) {
531581 result .asCall ( ) = this .asExpr ( )
532582 or
533583 this .( FlowSummaryNode ) .isOut ( result )
584+ or
585+ result = this .( ExceptionOutNode ) .getCall ( )
586+ }
587+
588+ /** Gets the kind of this returned value. */
589+ ReturnKind getKind ( ) {
590+ if this instanceof ExceptionOutNode
591+ then result instanceof ExceptionReturnKind
592+ else result instanceof NormalReturnKind
534593 }
535594 }
536595
@@ -597,6 +656,67 @@ module Private {
597656 cn .isInstanceAccess ( ) and result = cn .getEnclosingCallable ( ) .getDeclaringType ( )
598657 }
599658 }
659+
660+ /**
661+ * A data flow node that carries an exception and tests if it is caught in a
662+ * given catch clause.
663+ */
664+ class CatchTypeTestNode extends Node , TCatchTypeTestNode {
665+ override string toString ( ) { result = this .getCatch ( ) .toString ( ) }
666+
667+ override Location getLocation ( ) { result = this .getCatch ( ) .getLocation ( ) }
668+
669+ /** Gets the catch clause associated with this node. */
670+ CatchClause getCatch ( ) { this = TCatchTypeTestNode ( result ) }
671+
672+ Node getSuccessor ( boolean match ) {
673+ match = true and
674+ this .getCatch ( ) = result .( CatchParameterNode ) .getCatch ( )
675+ or
676+ match = false and
677+ exists ( TryStmt try , int i , CatchClause cc |
678+ cc = this .getCatch ( ) and
679+ cc = try .getCatchClause ( i ) and
680+ // A catch-all does not allow for uncaught exceptions.
681+ not cc .getACaughtType ( ) instanceof TypeThrowable and
682+ not cc .getACaughtType ( ) instanceof TypeException
683+ |
684+ result .( CatchTypeTestNode ) .getCatch ( ) = try .getCatchClause ( i + 1 )
685+ or
686+ not exists ( try .getCatchClause ( i + 1 ) ) and
687+ result .( UncaughtNode ) .getTry ( ) = try
688+ )
689+ }
690+ }
691+
692+ /**
693+ * A data flow node that holds the value of a variable defined in a catch
694+ * clause.
695+ */
696+ class CatchParameterNode extends Node , TCatchParameterNode {
697+ override string toString ( ) { result = this .getVariable ( ) .toString ( ) }
698+
699+ override Location getLocation ( ) { result = this .getVariable ( ) .getLocation ( ) }
700+
701+ /** Gets the catch clause associated with this node. */
702+ CatchClause getCatch ( ) { this = TCatchParameterNode ( result ) }
703+
704+ /** Gets the variable declaration associated with this node. */
705+ LocalVariableDeclExpr getVariable ( ) { result = this .getCatch ( ) .getVariable ( ) }
706+ }
707+
708+ /**
709+ * A data flow node that carries an exception that is uncaught by a try-catch
710+ * statement.
711+ */
712+ class UncaughtNode extends Node , TUncaughtNode {
713+ override string toString ( ) { result = "Uncaught exception" }
714+
715+ override Location getLocation ( ) { result = this .getTry ( ) .getLocation ( ) }
716+
717+ /** Gets the try statement associated with this node. */
718+ TryStmt getTry ( ) { this = TUncaughtNode ( result ) }
719+ }
600720}
601721
602722private import Private
0 commit comments