Skip to content

Commit 406cfff

Browse files
committed
Bug fixing of ABCIPanicChecker
1 parent edc6af8 commit 406cfff

File tree

7 files changed

+148
-62
lines changed

7 files changed

+148
-62
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package distribution
2+
3+
import (
4+
"time"
5+
6+
"github.com/cosmos/cosmos-sdk/telemetry"
7+
sdk "github.com/cosmos/cosmos-sdk/types"
8+
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
9+
"github.com/cosmos/cosmos-sdk/x/distribution/types"
10+
)
11+
12+
13+
func BeginBlocker(ctx sdk.Context, k keeper.Keeper) error {
14+
15+
ko()
16+
ok()
17+
ko()
18+
19+
return nil
20+
}
21+
22+
func ok(){
23+
defer func() {
24+
if r := recover(); r != nil {
25+
fmt.Println("Handle panic")
26+
}
27+
}()
28+
foo()
29+
}
30+
31+
func ko(){
32+
foo()
33+
}
34+
35+
func foo(){
36+
panic("HIGH HOPES!")
37+
}

go-lisa/src/main/java/it/unive/golisa/checker/cosmos/panic/ABCIPanicChecker.java

Lines changed: 53 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package it.unive.golisa.checker.cosmos.panic;
22

3-
import java.util.ArrayList;
43
import java.util.Collection;
54
import java.util.HashSet;
6-
import java.util.List;
75
import java.util.Set;
86

97
import it.unive.golisa.analysis.DummyDomain;
@@ -28,16 +26,13 @@
2826
import it.unive.lisa.analysis.types.InferredTypes;
2927
import it.unive.lisa.checks.semantic.CheckToolWithAnalysisResults;
3028
import it.unive.lisa.checks.semantic.SemanticCheck;
31-
import it.unive.lisa.checks.syntactic.CheckTool;
3229
import it.unive.lisa.program.cfg.CFG;
3330
import it.unive.lisa.program.cfg.CodeMember;
3431
import it.unive.lisa.program.cfg.CodeMemberDescriptor;
3532
import it.unive.lisa.program.cfg.statement.Expression;
3633
import it.unive.lisa.program.cfg.statement.Statement;
3734
import it.unive.lisa.program.cfg.statement.call.CFGCall;
3835
import 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
}

go-lisa/src/main/java/it/unive/golisa/checker/cosmos/panic/graph/PanicNode.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,22 @@ public PanicNode(GraphForCheckers graph, GoPanic st) {
1616
super(graph, st);
1717
}
1818

19+
@Override
20+
public int hashCode() {
21+
return super.hashCode();
22+
}
23+
24+
@Override
25+
public boolean equals(Object obj) {
26+
return super.equals(obj);
27+
}
28+
29+
@Override
30+
public PanicNode clone() throws CloneNotSupportedException {
31+
32+
return new PanicNode(getGraph(), (GoPanic) getStatement());
33+
}
34+
35+
36+
1937
}

go-lisa/src/main/java/it/unive/golisa/checker/cosmos/panic/graph/PossileRecoveryNode.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,11 @@ public PossileRecoveryNode(GraphForCheckers graph, GoDefer st) {
1616
super(graph, st);
1717
}
1818

19+
20+
@Override
21+
public PossileRecoveryNode clone() throws CloneNotSupportedException {
22+
23+
return new PossileRecoveryNode(getGraph(), (GoDefer) getStatement());
24+
}
25+
1926
}

go-lisa/src/main/java/it/unive/golisa/checker/cosmos/panic/graph/RecoveryNode.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,9 @@ public RecoveryNode(GraphForCheckers graph, GoDefer st) {
1616
super(graph, st);
1717
}
1818

19+
@Override
20+
public RecoveryNode clone() throws CloneNotSupportedException {
21+
22+
return new RecoveryNode(getGraph(), (GoDefer) getStatement());
23+
}
1924
}

go-lisa/src/main/java/it/unive/golisa/checker/utils/graph/GraphForCheckers.java

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.Iterator;
2222
import java.util.Map;
2323
import java.util.Map.Entry;
24+
import java.util.Objects;
2425
import java.util.Set;
2526
import java.util.SortedSet;
2627
import java.util.TreeSet;
@@ -32,7 +33,7 @@
3233

3334
public class GraphForCheckers extends CodeGraph<GraphForCheckers, StandardNode, LabeledEdge> implements Cloneable {
3435

35-
private final String name;
36+
private final String name;
3637

3738
public GraphForCheckers(String name) {
3839
super(new StandardEdge(null, null));
@@ -300,10 +301,12 @@ public StandardNode getNodeFromStatement(Statement statement) {
300301

301302
public void merge(GraphForCheckers other) throws CloneNotSupportedException {
302303
for(StandardNode n : other.getNodes()) {
303-
this.addNode(n.clone());
304+
if(!this.containsNode(n))
305+
this.addNode(n.clone());
304306
}
305307
for(LabeledEdge e : other.getEdges()) {
306-
this.addEdge(e.clone());
308+
if(!this.containsEdge(e))
309+
this.addEdge(e.clone());
307310
}
308311
}
309312

@@ -312,11 +315,31 @@ public GraphForCheckers clone() throws CloneNotSupportedException {
312315
GraphForCheckers clone = new GraphForCheckers(getName());
313316
for(StandardNode n : getNodes())
314317
clone.addNode(n.clone());
315-
for(LabeledEdge e : getEdges())
318+
for(LabeledEdge e : getEdges()) {
316319
clone.addEdge(e.clone());
320+
}
317321

318322
return clone;
319323
}
324+
325+
@Override
326+
public int hashCode() {
327+
return Objects.hash(name);
328+
}
329+
330+
@Override
331+
public boolean equals(Object obj) {
332+
if (this == obj)
333+
return true;
334+
if (obj == null)
335+
return false;
336+
if (getClass() != obj.getClass())
337+
return false;
338+
GraphForCheckers other = (GraphForCheckers) obj;
339+
return Objects.equals(name, other.name);
340+
}
341+
342+
320343

321344

322345
}

go-lisa/src/main/java/it/unive/golisa/checker/utils/graph/edges/LabeledEdge.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public boolean equals(Object obj) {
5050
if (getClass() != obj.getClass())
5151
return false;
5252
LabeledEdge other = (LabeledEdge) obj;
53-
return Objects.equals(destination, other.destination) && Objects.equals(source, other.source);
53+
return destination.equals(other.destination) && source.equals(other.source);
5454
}
5555

5656
@Override

0 commit comments

Comments
 (0)