11package it .unive .golisa .checker .cosmos .panic ;
22
3- import java .util .ArrayList ;
43import java .util .Collection ;
54import java .util .HashSet ;
6- import java .util .List ;
75import java .util .Set ;
86
97import it .unive .golisa .analysis .DummyDomain ;
2826import it .unive .lisa .analysis .types .InferredTypes ;
2927import it .unive .lisa .checks .semantic .CheckToolWithAnalysisResults ;
3028import it .unive .lisa .checks .semantic .SemanticCheck ;
31- import it .unive .lisa .checks .syntactic .CheckTool ;
3229import it .unive .lisa .program .cfg .CFG ;
3330import it .unive .lisa .program .cfg .CodeMember ;
3431import it .unive .lisa .program .cfg .CodeMemberDescriptor ;
3532import it .unive .lisa .program .cfg .statement .Expression ;
3633import it .unive .lisa .program .cfg .statement .Statement ;
3734import it .unive .lisa .program .cfg .statement .call .CFGCall ;
3835import it .unive .lisa .program .cfg .statement .call .Call ;
39- import javassist .expr .NewArray ;
40-
4136
4237/**
4338 * Unhandled errors Checker in Hyperledger Fabric.
@@ -64,14 +59,17 @@ public boolean visit(
6459 (GoPanic ) node , tool );
6560
6661 String printComponents = criticalComponentsToString (panicGraphWithRecoveries );
67- if (!existPossibleRecoveryDefer (panicGraphWithRecoveries )) {
68- tool .warnOn (node , "Detected unhandled panic within the following ABCI methods: "
69- + printComponents + ". Possible recovery functions not found ." );
62+ if (!( existPossibleRecoveryDefer (panicGraphWithRecoveries ) || existRecoveryDefer ( panicGraphWithRecoveries ) )) {
63+ tool .warnOn (node , "Detected unhandled panic within a critical execution "
64+ + printComponents + ". There are no execution paths with recovery function to handle the panic ." );
7065 } else {
71- // TODO: handle the case where at least one path is unhandled and the another is
72- // handled
73- tool .warnOn (node , "Detected panic within the following ABCI methods: " + printComponents
74- + ". Ensure that recovery functions properly handle the panic exception." );
66+ if (atLeastOnePathWithoutRecovery (panicGraphWithRecoveries )) {
67+ tool .warnOn (node , "Detected panic within a critical execution " + printComponents
68+ + ". There is at least an execution path without a recovery function." );
69+ } else {
70+ tool .warnOn (node , "Detected panic within a critical execution " + printComponents
71+ + ". Ensure that all the possible recovery functions properly handle the panic exception." );
72+ }
7573 }
7674
7775 }
@@ -95,13 +93,13 @@ private String criticalComponentsToString(GraphForCheckers panicGraphWithRecover
9593 return String .join ("," , signatures );
9694 }
9795
98-
99-
10096 private boolean existPossibleRecoveryDefer (GraphForCheckers panicGraphWithRecoveries ) {
101-
10297 return panicGraphWithRecoveries .getNodes ().stream ().anyMatch (n -> n instanceof PossileRecoveryNode );
10398 }
10499
100+ private boolean existRecoveryDefer (GraphForCheckers panicGraphWithRecoveries ) {
101+ return panicGraphWithRecoveries .getNodes ().stream ().anyMatch (n -> n instanceof RecoveryNode );
102+ }
105103
106104
107105 private GraphForCheckers computePossibleRecoveryDefers (GraphForCheckers panicGraph , GoPanic panic , CheckToolWithAnalysisResults <SimpleAbstractState <PointBasedHeap , ValueEnvironment <DummyDomain >, TypeEnvironment <InferredTypes >>> tool ) throws CloneNotSupportedException {
@@ -139,8 +137,10 @@ private void computePossibleRecoveryDefersRecursive(GraphForCheckers graphWithRe
139137
140138 Collection <LabeledEdge > ingoingEdges = graphWithRecovery .getIngoingEdges (stNode );
141139 if (!ingoingEdges .isEmpty ())
142- for (LabeledEdge e : ingoingEdges )
143- computePossibleRecoveryDefersRecursive (graphWithRecovery , e .getSource ().getStatement (), tool , seen );
140+ for (LabeledEdge e : ingoingEdges ) {
141+
142+ computePossibleRecoveryDefersRecursive (graphWithRecovery , e .getSource ().getStatement (), tool , new HashSet <>(seen ));
143+ }
144144 }
145145
146146 private boolean hasExplicitRecovery (GoDefer defer , CheckToolWithAnalysisResults <SimpleAbstractState <PointBasedHeap , ValueEnvironment <DummyDomain >, TypeEnvironment <InferredTypes >>> tool ) {
@@ -186,7 +186,7 @@ private GraphForCheckers extractPathCriticalComponentsInvolvedInPanicRecursive(S
186186 VariableScopingCFG callerCFG = (VariableScopingCFG ) cm ;
187187 Statement sTarget = CFGUtils .extractTargetNodeFromGraph (callerCFG , c );
188188 if (sTarget != null ) {
189- GraphForCheckers tmp = extractPathCriticalComponentsInvolvedInPanicRecursive (sTarget , sTarget , graph , tool , seen );
189+ GraphForCheckers tmp = extractPathCriticalComponentsInvolvedInPanicRecursive (sTarget , node , graph , tool , new HashSet <>( seen ) );
190190 if (tmp != null ) {
191191 graph .merge (tmp );
192192 }
@@ -196,55 +196,51 @@ private GraphForCheckers extractPathCriticalComponentsInvolvedInPanicRecursive(S
196196 }
197197 }
198198 }
199+ } else {
200+ throw new UnsupportedOperationException ("The analysis on cyclic graphs are currently not supported" );
199201 }
200202 return graph ;
201203 }
202204
203-
204-
205- private Set <CodeMemberDescriptor > extractCriticalComponentsInvolvedInPanic (GoPanic panic , CheckToolWithAnalysisResults <SimpleAbstractState <PointBasedHeap , ValueEnvironment <DummyDomain >, TypeEnvironment <InferredTypes >>> tool ) {
206- Set <CodeMember > seen = new HashSet <>();
207- return extractCriticalComponentsRecursive (panic , tool , seen );
205+ private boolean isCriticalComponent (CodeMemberDescriptor descriptor ) {
206+ return descriptor .getSignature ().contains ("BeginBlocker" )
207+ || descriptor .getSignature ().contains ("EndBlocker" );
208208 }
209209
210- private Set <CodeMemberDescriptor > extractCriticalComponentsRecursive (Statement node , CheckToolWithAnalysisResults <SimpleAbstractState <PointBasedHeap , ValueEnvironment <DummyDomain >, TypeEnvironment <InferredTypes >>> tool , Set <CodeMember > seen ) {
211- Set <CodeMemberDescriptor > result = new HashSet <>();
212- if (!seen .contains (node .getCFG ())) {
213- seen .add (node .getCFG ());
214- if (isCriticalComponent (node .getCFG ().getDescriptor ())) {
215- result .add (node .getCFG ().getDescriptor ());
216- } else {
217- // check callers of CFG recursively
218- Collection <CodeMember > callers = tool .getCallers (node .getCFG ());
219-
220- for (CodeMember cm : callers ) {
221- if (!seen .contains (cm )) {
222- seen .add (cm );
223210
224- for (Call c : tool .getCallSites (node .getCFG ())) {
225- if (cm instanceof VariableScopingCFG ) {
226- VariableScopingCFG callerCFG = (VariableScopingCFG ) cm ;
227- Statement sTarget = CFGUtils .extractTargetNodeFromGraph (callerCFG , c );
228- if (sTarget != null ) {
229- result .addAll (extractCriticalComponentsRecursive (sTarget , tool , seen ));
230- }
231- }
232- }
233- }
234- }
211+ private boolean atLeastOnePathWithoutRecovery (GraphForCheckers panicGraphWithRecoveries ) {
212+ Set <Statement > seen = new HashSet <>();
213+ PanicNode panicNode = null ;
214+ for (StandardNode n : panicGraphWithRecoveries .getNodes ())
215+ if (n instanceof PanicNode ) {
216+ panicNode = (PanicNode ) n ;
217+ break ;
235218 }
236- }
237- return result ;
238- }
239-
240- private boolean isCriticalComponent (CodeMemberDescriptor descriptor ) {
241- return descriptor .getSignature ().contains ("BeginBlocker" )
242- || descriptor .getSignature ().contains ("EndBlocker" );
219+
220+ return atLeastOnePathWithoutRecoveryRecursive (panicGraphWithRecoveries , panicNode .getStatement (), seen );
243221 }
222+
223+ private boolean atLeastOnePathWithoutRecoveryRecursive (GraphForCheckers panicGraphWithRecoveries , Statement st , Set <Statement > seen ) {
244224
245- private Set <Statement > extractPossibleRecoveryDefer (Statement node ) {
246- // TODO Auto-generated method stub
247- return null ;
225+ if (seen .contains (st ))
226+ return false ;
227+ seen .add (st );
228+
229+ StandardNode stNode = panicGraphWithRecoveries .getNodeFromStatement (st );
230+
231+ if (stNode instanceof PossileRecoveryNode || stNode instanceof RecoveryNode )
232+ return false ;
233+
234+ if (isCriticalComponent (st .getCFG ().getDescriptor ()))
235+ return true ;
236+
237+ Collection <LabeledEdge > ingoingEdges = panicGraphWithRecoveries .getIngoingEdges (stNode );
238+ if (!ingoingEdges .isEmpty ())
239+ for (LabeledEdge e : ingoingEdges ) {
240+ if (atLeastOnePathWithoutRecoveryRecursive (panicGraphWithRecoveries , e .getSource ().getStatement (), new HashSet <>(seen )))
241+ return true ;
242+ }
243+ return false ;
248244 }
249245
250246}
0 commit comments