|
1 | 1 | package it.unive.golisa.checker.hf; |
2 | 2 |
|
| 3 | +import java.util.HashMap; |
| 4 | +import java.util.Map; |
| 5 | + |
3 | 6 | import it.unive.golisa.cfg.statement.assignment.GoAssignment; |
4 | 7 | import it.unive.golisa.cfg.statement.assignment.GoMultiAssignment; |
5 | 8 | import it.unive.golisa.cfg.utils.CFGUtils; |
|
26 | 29 | */ |
27 | 30 | public class UnhandledErrorsChecker implements SyntacticCheck { |
28 | 31 |
|
| 32 | + private Map<Call, Boolean> assignmentMap; |
| 33 | + |
29 | 34 | @Override |
30 | 35 | public void beforeExecution(CheckTool tool) { |
| 36 | + |
| 37 | + assignmentMap = new HashMap<>(); |
31 | 38 | } |
32 | 39 |
|
33 | 40 | @Override |
34 | 41 | 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 | + } |
35 | 51 | } |
36 | 52 |
|
37 | 53 | @Override |
38 | 54 | 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 | + } |
39 | 62 |
|
40 | 63 | if (node instanceof GoMultiAssignment) { |
41 | 64 | GoMultiAssignment multiAssign = (GoMultiAssignment) node; |
42 | 65 | Expression expr = multiAssign.getExpressionToAssign(); |
43 | 66 | if (expr instanceof Call) { |
44 | 67 | if (ReadWriteHFUtils.isReadOrWriteCall((Call) expr)) { |
| 68 | + assignmentMap.put((Call) expr, Boolean.TRUE); |
45 | 69 | if (multiAssign.getIds().length == 2) |
46 | 70 | 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); |
74 | 72 | } |
| 73 | + } |
75 | 74 |
|
| 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 | + } |
76 | 88 | } |
77 | 89 |
|
78 | 90 | } |
79 | 91 | } |
| 92 | + |
80 | 93 | return true; |
81 | 94 | } |
82 | 95 |
|
| 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 | + |
83 | 125 | private boolean existVariableOverwriteInPath(CodeGraph<CFG, Statement, Edge> path, Statement node, |
84 | 126 | VariableRef ref) { |
85 | 127 | for (Statement n : path.getNodeList()) { |
|
0 commit comments