Skip to content

Commit 2709ea7

Browse files
committed
Improving checks for unhandled error issues
1 parent 9852eed commit 2709ea7

File tree

4 files changed

+76
-35
lines changed

4 files changed

+76
-35
lines changed

go-lisa/go-testcases/unhandled-errors/hf-unhandled-errors.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
1717
value1, _ := stub.GetState(args[0]) // KO: error is discarded
1818

1919
stub.PutState(args[0], []byte("ASD")) // KO: error is discarded
20+
21+
_ = stub.PutState(args[0], []byte("ASD")) // KO: error is discarded
2022

2123
value2, err := stub.GetState(args[1]) // KO: error is not handled
2224

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

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -147,18 +147,11 @@ private boolean hasExplicitRecovery(GoDefer defer, CheckToolWithAnalysisResults<
147147
Expression expr = defer.getSubExpression();
148148
if(expr instanceof CFGCall) {
149149
CFGCall call = (CFGCall) expr;
150-
return call.getTargetedCFGs().stream().anyMatch(cfg -> cfg.getNodes().stream().anyMatch(n -> n instanceof GoRecover || containsRecover(n)));
150+
return call.getTargetedCFGs().stream().anyMatch(cfg -> cfg.getNodes().stream().anyMatch(n -> CFGUtils.matchNodeOrSubExpressions(n, st -> st instanceof GoRecover)));
151151
}
152152
return false;
153153
}
154154

155-
156-
private boolean containsRecover(Statement n) {
157-
158-
return n instanceof GoRecover;
159-
}
160-
161-
162155
private GraphForCheckers extractPathCriticalComponentsInvolvedInPanic(GoPanic node,
163156
CheckToolWithAnalysisResults<SimpleAbstractState<PointBasedHeap, ValueEnvironment<DummyDomain>, TypeEnvironment<InferredTypes>>> tool) throws CloneNotSupportedException {
164157
GraphForCheckers graph = new GraphForCheckers(node.getLocation().toString());

go-lisa/src/main/java/it/unive/golisa/checker/hf/UnhandledErrorsChecker.java

Lines changed: 69 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package it.unive.golisa.checker.hf;
22

3+
import java.util.HashMap;
4+
import java.util.Map;
5+
36
import it.unive.golisa.cfg.statement.assignment.GoAssignment;
47
import it.unive.golisa.cfg.statement.assignment.GoMultiAssignment;
58
import it.unive.golisa.cfg.utils.CFGUtils;
@@ -26,60 +29,99 @@
2629
*/
2730
public class UnhandledErrorsChecker implements SyntacticCheck {
2831

32+
private Map<Call, Boolean> assignmentMap;
33+
2934
@Override
3035
public void beforeExecution(CheckTool tool) {
36+
37+
assignmentMap = new HashMap<>();
3138
}
3239

3340
@Override
3441
public void afterExecution(CheckTool tool) {
42+
43+
for(Call call : assignmentMap.keySet()) {
44+
if(!assignmentMap.get(call).booleanValue()) {
45+
tool.warnOn(call, "Unhandled error of a blockchain "
46+
+ (ReadWriteHFUtils.isReadCall((Call) call) ? "read" : "write")
47+
+ " operation. The error seems not assigned in any variable");
48+
}
49+
50+
}
3551
}
3652

3753
@Override
3854
public boolean visit(CheckTool tool, CFG graph, Statement node) {
55+
56+
if (node instanceof Call) {
57+
if (ReadWriteHFUtils.isReadOrWriteCall((Call) node)) {
58+
if(!assignmentMap.containsKey((Call) node))
59+
assignmentMap.put((Call) node, Boolean.FALSE);
60+
}
61+
}
3962

4063
if (node instanceof GoMultiAssignment) {
4164
GoMultiAssignment multiAssign = (GoMultiAssignment) node;
4265
Expression expr = multiAssign.getExpressionToAssign();
4366
if (expr instanceof Call) {
4467
if (ReadWriteHFUtils.isReadOrWriteCall((Call) expr)) {
68+
assignmentMap.put((Call) expr, Boolean.TRUE);
4569
if (multiAssign.getIds().length == 2)
4670
if (multiAssign.getIds()[1] instanceof VariableRef) {
47-
VariableRef ref = (VariableRef) multiAssign.getIds()[1];
48-
if (GoLangUtils.isBlankIdentifier(ref.getVariable()))
49-
tool.warnOn(node,
50-
"Unhandled error of a blockchain "
51-
+ (ReadWriteHFUtils.isReadCall((Call) expr) ? "read" : "write")
52-
+ " operation. It is discarded during the assignment.");
53-
else {
54-
boolean found = false;
55-
for (ControlFlowStructure cfs : graph.getControlFlowStructures()) {
56-
if (cfs instanceof IfThenElse) {
57-
CodeGraph<CFG, Statement,
58-
Edge> path = CFGUtils.getPath(graph, node, cfs.getCondition());
59-
if (path != null
60-
&& !existVariableOverwriteInPath(path, node, ref)
61-
&& isVariableRefUsedInCondition(ref, cfs.getCondition())) {
62-
found = true;
63-
break;
64-
}
65-
}
66-
67-
}
68-
69-
if (!found)
70-
tool.warnOn(node, "Unhandled error of a blockchain "
71-
+ (ReadWriteHFUtils.isReadCall((Call) expr) ? "read" : "write")
72-
+ " operation. It seems not checked in any condition statements in the method");
73-
}
71+
checkVariableRef((VariableRef) multiAssign.getIds()[1], (Call) expr, tool, graph, node);
7472
}
73+
}
7574

75+
}
76+
}
77+
78+
if (node instanceof GoAssignment) {
79+
GoAssignment assign = (GoAssignment) node;
80+
Expression right = assign.getRight();
81+
if (right instanceof Call) {
82+
if (ReadWriteHFUtils.isWriteCall((Call) right)) {
83+
assignmentMap.put((Call) right, Boolean.TRUE);
84+
Expression left = assign.getLeft();
85+
if (left instanceof VariableRef) {
86+
checkVariableRef((VariableRef) left, (Call) right, tool, graph, node);
87+
}
7688
}
7789

7890
}
7991
}
92+
8093
return true;
8194
}
8295

96+
private void checkVariableRef( VariableRef ref, Call call, CheckTool tool, CFG graph, Statement node) {
97+
if (GoLangUtils.isBlankIdentifier(ref.getVariable()))
98+
tool.warnOn(node,
99+
"Unhandled error of a blockchain "
100+
+ (ReadWriteHFUtils.isReadCall(call) ? "read" : "write")
101+
+ " operation. It is discarded during the assignment.");
102+
else {
103+
boolean found = false;
104+
for (ControlFlowStructure cfs : graph.getControlFlowStructures()) {
105+
if (cfs instanceof IfThenElse) {
106+
CodeGraph<CFG, Statement,
107+
Edge> path = CFGUtils.getPath(graph, node, cfs.getCondition());
108+
if (path != null
109+
&& !existVariableOverwriteInPath(path, node, ref)
110+
&& isVariableRefUsedInCondition(ref, cfs.getCondition())) {
111+
found = true;
112+
break;
113+
}
114+
}
115+
116+
}
117+
118+
if (!found)
119+
tool.warnOn(node, "Unhandled error of a blockchain "
120+
+ (ReadWriteHFUtils.isReadCall(call) ? "read" : "write")
121+
+ " operation. It seems not checked in any condition statements in the method");
122+
}
123+
}
124+
83125
private boolean existVariableOverwriteInPath(CodeGraph<CFG, Statement, Edge> path, Statement node,
84126
VariableRef ref) {
85127
for (Statement n : path.getNodeList()) {

go-lisa/src/main/java/it/unive/golisa/frontend/GoCodeMemberVisitor.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
import it.unive.golisa.cfg.expression.GoMake;
9393
import it.unive.golisa.cfg.expression.GoNew;
9494
import it.unive.golisa.cfg.expression.GoPanic;
95+
import it.unive.golisa.cfg.expression.GoRecover;
9596
import it.unive.golisa.cfg.expression.GoTypeConversion;
9697
import it.unive.golisa.cfg.expression.binary.GoBitwiseAnd;
9798
import it.unive.golisa.cfg.expression.binary.GoBitwiseNAnd;
@@ -2163,6 +2164,9 @@ public Expression visitPrimaryExpr(PrimaryExprContext ctx) {
21632164
} else {
21642165
return new GoMake(cfg, locationOf(ctx.primaryExpr()), Untyped.INSTANCE, args);
21652166
}
2167+
case "recover":
2168+
args = visitArguments(ctx.arguments());
2169+
return new GoRecover(cfg, locationOf(ctx.primaryExpr()));
21662170
case "panic":
21672171
args = visitArguments(ctx.arguments());
21682172
return new GoPanic(cfg, locationOf(ctx.primaryExpr()), args);

0 commit comments

Comments
 (0)