Skip to content

Commit 016edc5

Browse files
committed
Fixed bug: all nodes and edges are correctly added to xCFG
Specifically, updated ProgramCounterLocation
1 parent 40b386d commit 016edc5

File tree

7 files changed

+402
-256
lines changed

7 files changed

+402
-256
lines changed

src/main/java/it/unipr/cfg/EVMCFG.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ public class EVMCFG extends CFG {
4141
public Set<Statement> pushedJumps;
4242
public Set<Statement> sstores;
4343
public Set<Statement> sha3s;
44-
public List<Statement> logxs;
45-
public List<Statement> calls;
44+
public Set<Statement> logxs;
45+
public Set<Statement> calls;
4646

4747
public EVMCFG(CodeMemberDescriptor descriptor, Collection<Statement> entrypoints,
4848
NodeList<CFG, Statement, Edge> list) {
@@ -54,16 +54,16 @@ public EVMCFG(CodeMemberDescriptor cfgDesc) {
5454
}
5555

5656
/**
57-
* Returns a list of all the CALL, STATICCALL and DELEGATECALL statements in
57+
* Returns a set of all the CALL, STATICCALL and DELEGATECALL statements in
5858
* the CFG.
5959
*
60-
* @return a list of all the CALL, STATICCALL and DELEGATECALL statements in
60+
* @return a set of all the CALL, STATICCALL and DELEGATECALL statements in
6161
* the CFG
6262
*/
63-
public List<Statement> getAllCall() {
63+
public Set<Statement> getAllCall() {
6464
if (this.calls == null) {
6565
NodeList<CFG, Statement, Edge> cfgNodeList = this.getNodeList();
66-
List<Statement> calls = new ArrayList<>();
66+
Set<Statement> calls = new HashSet<>();
6767

6868
for (Statement statement : cfgNodeList.getNodes()) {
6969
if (statement instanceof Call) {
@@ -82,14 +82,14 @@ public List<Statement> getAllCall() {
8282
}
8383

8484
/**
85-
* Returns a list of all the LOGx statements in the CFG.
85+
* Returns a set of all the LOGx statements in the CFG.
8686
*
87-
* @return a list of all the LOGx statements in the CFG
87+
* @return a set of all the LOGx statements in the CFG
8888
*/
89-
public List<Statement> getAllLogX() {
89+
public Set<Statement> getAllLogX() {
9090
if (logxs == null) {
9191
NodeList<CFG, Statement, Edge> cfgNodeList = this.getNodeList();
92-
List<Statement> logxs = new ArrayList<>();
92+
Set<Statement> logxs = new HashSet<>();
9393

9494
for (Statement statement : cfgNodeList.getNodes()) {
9595
if (statement instanceof Log) {

src/main/java/it/unipr/cfg/ProgramCounterLocation.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,34 @@ public class ProgramCounterLocation implements CodeLocation {
1010

1111
private final int pc;
1212
private final int sourceCodeLine;
13+
private final int cfgHashCode;
1314

1415
/**
15-
* Default constructor.
16-
*
17-
* @param pc integer representing the code location of the opcode
16+
* Constructs a {@code ProgramCounterLocation} with the specified program
17+
* counter (PC) and source code line.
18+
*
19+
* @param pc the integer representing the code location of the
20+
* opcode
21+
* @param sourceCodeLine the corresponding line number in the source code
1822
*/
1923
public ProgramCounterLocation(int pc, int sourceCodeLine) {
24+
this(pc, sourceCodeLine, 0);
25+
}
26+
27+
/**
28+
* Constructs a {@code ProgramCounterLocation} with the specified program
29+
* counter (PC), source code line, and control flow graph (CFG) hash code.
30+
*
31+
* @param pc the integer representing the code location of the
32+
* opcode
33+
* @param sourceCodeLine the corresponding line number in the source code
34+
* @param cfgHashCode the hash code of the associated control flow graph
35+
* (CFG)
36+
*/
37+
public ProgramCounterLocation(int pc, int sourceCodeLine, int cfgHashCode) {
2038
this.pc = pc;
2139
this.sourceCodeLine = sourceCodeLine;
40+
this.cfgHashCode = cfgHashCode;
2241
}
2342

2443
@Override
@@ -45,7 +64,7 @@ public String getCodeLocation() {
4564

4665
@Override
4766
public int hashCode() {
48-
return Objects.hash(pc);
67+
return Objects.hash(pc) + Objects.hash(sourceCodeLine) + Objects.hash(cfgHashCode);
4968
}
5069

5170
@Override
@@ -62,7 +81,7 @@ public boolean equals(Object obj) {
6281
if (getClass() != obj.getClass())
6382
return false;
6483
ProgramCounterLocation other = (ProgramCounterLocation) obj;
65-
return pc == other.pc;
84+
return pc == other.pc && cfgHashCode == other.cfgHashCode && sourceCodeLine == other.sourceCodeLine;
6685
}
6786

6887
/**
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package it.unipr.checker;
2+
3+
import it.unipr.analysis.AbstractStack;
4+
import it.unipr.analysis.EVMAbstractState;
5+
import it.unipr.analysis.taint.TaintAbstractDomain;
6+
import it.unipr.cfg.Calldataload;
7+
import it.unipr.cfg.EVMCFG;
8+
import it.unipr.cfg.ProgramCounterLocation;
9+
import it.unipr.utils.MyCache;
10+
import it.unive.lisa.analysis.AnalysisState;
11+
import it.unive.lisa.analysis.AnalyzedCFG;
12+
import it.unive.lisa.analysis.SemanticException;
13+
import it.unive.lisa.analysis.SimpleAbstractState;
14+
import it.unive.lisa.analysis.heap.MonolithicHeap;
15+
import it.unive.lisa.analysis.nonrelational.value.TypeEnvironment;
16+
import it.unive.lisa.analysis.types.InferredTypes;
17+
import it.unive.lisa.checks.semantic.CheckToolWithAnalysisResults;
18+
import it.unive.lisa.checks.semantic.SemanticCheck;
19+
import it.unive.lisa.program.cfg.CFG;
20+
import it.unive.lisa.program.cfg.statement.Statement;
21+
import java.util.Set;
22+
import org.apache.logging.log4j.LogManager;
23+
import org.apache.logging.log4j.Logger;
24+
25+
public class CallDataLoadChecker implements
26+
SemanticCheck<SimpleAbstractState<MonolithicHeap, EVMAbstractState, TypeEnvironment<InferredTypes>>> {
27+
28+
private static final Logger log = LogManager.getLogger(CallDataLoadChecker.class);
29+
30+
@Override
31+
public boolean visit(
32+
CheckToolWithAnalysisResults<
33+
SimpleAbstractState<MonolithicHeap, EVMAbstractState, TypeEnvironment<InferredTypes>>> tool,
34+
CFG graph, Statement node) {
35+
36+
if (node instanceof Calldataload) {
37+
EVMCFG cfg = ((EVMCFG) graph);
38+
Statement callDataLoad = node;
39+
40+
for (AnalyzedCFG<SimpleAbstractState<MonolithicHeap, EVMAbstractState,
41+
TypeEnvironment<InferredTypes>>> result : tool.getResultOf(cfg)) {
42+
AnalysisState<SimpleAbstractState<MonolithicHeap, EVMAbstractState,
43+
TypeEnvironment<InferredTypes>>> analysisResult = null;
44+
45+
try {
46+
analysisResult = result.getAnalysisStateBefore(callDataLoad);
47+
} catch (SemanticException e1) {
48+
log.error("(CallDataLoadChecker): {}", e1.getMessage());
49+
}
50+
51+
// Retrieve the symbolic stack from the analysis result
52+
EVMAbstractState valueState = analysisResult.getState().getValueState();
53+
54+
// If the value state is bottom, the jump is definitely
55+
// unreachable
56+
if (valueState.isBottom())
57+
// Nothing to do
58+
continue;
59+
else if (valueState.isTop())
60+
continue;
61+
else {
62+
for (AbstractStack stack : valueState.getStacks()) {
63+
log.debug(stack);
64+
}
65+
}
66+
}
67+
}
68+
69+
return true;
70+
}
71+
72+
private void checkForUncheckedStateUpdate(Statement sstore, CheckToolWithAnalysisResults<
73+
SimpleAbstractState<MonolithicHeap, TaintAbstractDomain, TypeEnvironment<InferredTypes>>> tool,
74+
EVMCFG cfg) {
75+
76+
Set<Statement> jumps = cfg.getAllJumpI();
77+
Set<Statement> calls = cfg.getAllCall();
78+
79+
for (Statement call : calls) {
80+
if (cfg.reachableFrom(call, sstore)) {
81+
if (!cfg.reachableFromCrossing(call, sstore, jumps)) {
82+
83+
ProgramCounterLocation sstoreLocation = (ProgramCounterLocation) sstore.getLocation();
84+
85+
log.warn("Unchecked State Update vulnerability at {} at line no. {} coming from line {}",
86+
sstoreLocation.getPc(),
87+
sstoreLocation.getSourceCodeLine(),
88+
((ProgramCounterLocation) call.getLocation()).getSourceCodeLine());
89+
90+
String warn = "Unchecked State Update vulnerability at "
91+
+ ((ProgramCounterLocation) call.getLocation()).getSourceCodeLine();
92+
tool.warn(warn);
93+
MyCache.getInstance().addUncheckedStateUpdateWarning(cfg.hashCode(), warn);
94+
}
95+
}
96+
}
97+
}
98+
}

src/main/java/it/unipr/checker/UncheckedStateUpdateChecker.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import it.unive.lisa.checks.semantic.SemanticCheck;
1818
import it.unive.lisa.program.cfg.CFG;
1919
import it.unive.lisa.program.cfg.statement.Statement;
20-
import java.util.List;
2120
import java.util.Set;
2221
import org.apache.logging.log4j.LogManager;
2322
import org.apache.logging.log4j.Logger;
@@ -79,7 +78,7 @@ private void checkForUncheckedStateUpdate(Statement sstore, CheckToolWithAnalysi
7978
EVMCFG cfg) {
8079

8180
Set<Statement> jumps = cfg.getAllJumpI();
82-
List<Statement> calls = cfg.getAllCall();
81+
Set<Statement> calls = cfg.getAllCall();
8382

8483
for (Statement call : calls) {
8584
if (cfg.reachableFrom(call, sstore)) {

0 commit comments

Comments
 (0)