Skip to content

Commit 449e715

Browse files
committed
Refactored VulnerableLOGsComputer to utilize event signatures and improved logging for local dependency analysis
1 parent 06fd3d0 commit 449e715

File tree

2 files changed

+56
-40
lines changed

2 files changed

+56
-40
lines changed

src/main/java/it/unipr/crosschain/checker/VulnerableLOGsComputer.java

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package it.unipr.crosschain.checker;
22

3+
import it.unipr.analysis.contract.Signature;
34
import it.unipr.analysis.taint.TaintAbstractDomain;
45
import it.unipr.analysis.taint.TaintElement;
56
import it.unipr.cfg.*;
@@ -15,22 +16,30 @@
1516
import it.unive.lisa.checks.semantic.SemanticCheck;
1617
import it.unive.lisa.program.cfg.CFG;
1718
import it.unive.lisa.program.cfg.statement.Statement;
19+
import java.util.HashSet;
20+
import java.util.Set;
1821
import org.apache.logging.log4j.LogManager;
1922
import org.apache.logging.log4j.Logger;
2023

2124
public class VulnerableLOGsComputer implements
2225
SemanticCheck<SimpleAbstractState<MonolithicHeap, TaintAbstractDomain, TypeEnvironment<InferredTypes>>> {
2326

2427
private static final Logger log = LogManager.getLogger(VulnerableLOGsComputer.class);
28+
private Set<Statement> eventsExitpoints;
29+
30+
public VulnerableLOGsComputer(Set<Signature> events) {
31+
this.eventsExitpoints = new HashSet<>();
32+
for (Signature event : events)
33+
eventsExitpoints.addAll(event.getExitPoints());
34+
}
2535

2636
@Override
2737
public boolean visit(
2838
CheckToolWithAnalysisResults<
2939
SimpleAbstractState<MonolithicHeap, TaintAbstractDomain, TypeEnvironment<InferredTypes>>> tool,
3040
CFG graph, Statement node) {
3141

32-
if (node instanceof Log) {
33-
42+
if (eventsExitpoints.contains(node)) {
3443
EVMCFG cfg = ((EVMCFG) graph);
3544

3645
for (AnalyzedCFG<SimpleAbstractState<MonolithicHeap, TaintAbstractDomain,
@@ -47,43 +56,45 @@ public boolean visit(
4756
// Retrieve the symbolic stack from the analysis result
4857
TaintAbstractDomain taintedStack = analysisResult.getState().getValueState();
4958

50-
if (taintedStack.isBottom())
59+
if (taintedStack.isBottom() || taintedStack.isTop())
5160
// Nothing to do
5261
continue;
53-
else {
54-
if (node instanceof Log1)
55-
if (TaintElement.isAtLeastOneTainted(taintedStack.getElementAtPosition(1),
56-
taintedStack.getElementAtPosition(2),
57-
taintedStack.getElementAtPosition(3)))
58-
addVulnerableLOG(node);
59-
if (node instanceof Log2)
60-
if (TaintElement.isAtLeastOneTainted(taintedStack.getElementAtPosition(1),
61-
taintedStack.getElementAtPosition(2),
62-
taintedStack.getElementAtPosition(3),
63-
taintedStack.getElementAtPosition(4)))
64-
addVulnerableLOG(node);
65-
if (node instanceof Log3)
66-
if (TaintElement.isAtLeastOneTainted(taintedStack.getElementAtPosition(1),
67-
taintedStack.getElementAtPosition(2),
68-
taintedStack.getElementAtPosition(3),
69-
taintedStack.getElementAtPosition(4),
70-
taintedStack.getElementAtPosition(5)))
71-
addVulnerableLOG(node);
72-
if (node instanceof Log4)
73-
if (TaintElement.isAtLeastOneTainted(taintedStack.getElementAtPosition(1),
74-
taintedStack.getElementAtPosition(2),
75-
taintedStack.getElementAtPosition(3),
76-
taintedStack.getElementAtPosition(4),
77-
taintedStack.getElementAtPosition(5),
78-
taintedStack.getElementAtPosition(6)))
79-
addVulnerableLOG(node);
80-
}
62+
63+
int numArgs = getNumberOfArgs(node);
64+
boolean isAtLeastOneTainted = false;
65+
66+
for (int argIndex = 1; argIndex <= numArgs; argIndex++)
67+
isAtLeastOneTainted |= TaintElement.isAtLeastOneTainted(
68+
taintedStack.getElementAtPosition(argIndex));
69+
70+
if (isAtLeastOneTainted)
71+
addVulnerableLOG(node);
8172
}
8273
}
8374

8475
return true;
8576
}
8677

78+
/**
79+
* Computes the number of arguments consumed from the stack by the provided
80+
* EVM instruction.
81+
*
82+
* @param node the statement to inspect
83+
*
84+
* @return the amount of stack elements consumed by {@code node}
85+
*/
86+
private int getNumberOfArgs(Statement node) {
87+
if (node instanceof Log1)
88+
return 3;
89+
if (node instanceof Log2)
90+
return 4;
91+
if (node instanceof Log3)
92+
return 5;
93+
if (node instanceof Log4)
94+
return 6;
95+
return 0;
96+
}
97+
8798
/**
8899
* Adds a vulnerable log statement to the time synchronization checker and
89100
* logs a warning message indicating the potential vulnerability.
@@ -95,7 +106,7 @@ private void addVulnerableLOG(Statement node) {
95106
MyCache.getInstance().addVulnerableLogStatementForLocalDependencyChecker(node);
96107

97108
ProgramCounterLocation nodeLocation = (ProgramCounterLocation) node.getLocation();
98-
log.warn("(Time Synchronization vulnerability) LOG possibly vulnerable at pc {} (line {}) (cfg={}).",
109+
log.warn("(Local Dependency Checker) Event possibly vulnerable at pc {} (line {}) (cfg={}).",
99110
nodeLocation.getPc(),
100111
nodeLocation.getSourceCodeLine(),
101112
node.getCFG().hashCode());

src/main/java/it/unipr/crosschain/xEVMLiSA.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -287,10 +287,10 @@ public static void runCrossChainCheckers(Bridge bridge) {
287287
/**
288288
* Executes the Local Dependency analysis for all contracts in the given
289289
* bridge. This method performs three phases in parallel across all
290-
* contracts: (i) Identify vulnerable LOG statements for the Local
291-
* Dependency Checker. (ii) Mark any CALLDATALOAD sites reachable from those
292-
* LOGs as tainted. (iii) Run the core Local Dependency Checker logic on
293-
* each contract.
290+
* contracts: (i) Identify vulnerable Event statements for the Local
291+
* Dependency Checker. (ii) Mark any CALLDATALOAD or CALLDATACOPY sites
292+
* reachable from those LOGs as tainted. (iii) Run the core Local Dependency
293+
* Checker logic on each contract.
294294
*
295295
* @param bridge the Bridge instance whose contracts will be analyzed
296296
*/
@@ -569,7 +569,7 @@ public static void computeVulnerablesLOGsForLocalDependencyChecker(SmartContract
569569
LiSAConfiguration conf = LiSAConfigurationManager.createConfiguration(contract);
570570
LiSA lisa = new LiSA(conf);
571571

572-
VulnerableLOGsComputer checker = new VulnerableLOGsComputer();
572+
VulnerableLOGsComputer checker = new VulnerableLOGsComputer(contract.getEventsSignature());
573573
conf.semanticChecks.add(checker);
574574
conf.abstractState = new SimpleAbstractState<>(new MonolithicHeap(),
575575
new VulnerableLOGsAbstractDomain(),
@@ -597,12 +597,17 @@ public static void computeTaintedCallDataForLocalDependencyChecker(SmartContract
597597
for (Signature event : contract.getEventsSignature()) {
598598
for (Statement emit : event.getExitPoints()) {
599599
if (logsVulnerable.contains(emit)) {
600+
600601
/* Functions linked to this event */
601602
Set<Signature> functionsLinked = MyCache.getInstance().getMapEventsFunctions(event);
602-
log.warn("No linked function found for event {} in contract {}.", event.getFullSignature(),
603-
contract.getName());
604-
for (Signature functionLinked : functionsLinked) {
605603

604+
if (functionsLinked.isEmpty()) {
605+
log.warn("No linked function found for event {} in contract {}.", event.getFullSignature(),
606+
contract.getName());
607+
continue;
608+
}
609+
610+
for (Signature functionLinked : functionsLinked) {
606611
for (Statement entrypoint : functionLinked.getEntryPoints()) {
607612
for (Statement exitpoint : functionLinked.getExitPoints()) {
608613
/*

0 commit comments

Comments
 (0)