From feac4c501bd95b2188e4dace711ff0b77f180097 Mon Sep 17 00:00:00 2001 From: merendamattia Date: Thu, 31 Jul 2025 10:25:20 +0200 Subject: [PATCH] Added option to show all instructions in CFG representation (#53) --- README.md | 33 ++++++++++--------- src/main/java/it/unipr/EVMLiSA.java | 10 ++++++ .../java/it/unipr/utils/DOTFileManager.java | 19 ++++++++++- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index fbd00826e..fec1164de 100644 --- a/README.md +++ b/README.md @@ -98,23 +98,24 @@ Alternatively, you can pass your API key directly using the `--etherscan-api-key ``` Options: - -a,--address Address of an Ethereum smart contract + -a,--address Address of an Ethereum smart contract. --abi ABI of the bytecode to be analyzed (JSON format). - --abi-path Filepath of the ABI file - -b,--bytecode Bytecode to be analyzed (e.g., 0x6080...) - --benchmark Filepath of the benchmark - --bytecode-path Filepath of the bytecode file - -c,--cores Number of cores used in benchmark - --checker-all Enable all security checkers - --checker-reentrancy Enable reentrancy checker - --checker-timestampdependency Enable timestamp-dependency checker - --checker-txorigin Enable tx-origin checker - --etherscan-api-key Insert your Etherscan API key - --link-unsound-jumps-to-all-jumpdest Link all unsound jumps to all jumpdest - --output-directory-path Filepath of the output directory - --stack-set-size Dimension of stack-set (default: 8) - --stack-size Dimension of stack (default: 32) - --use-live-storage Use the live storage in SLOAD + --abi-path Filepath of the ABI file. + -b,--bytecode Bytecode to be analyzed (e.g., 0x6080...). + --benchmark Filepath of the benchmark. + --bytecode-path Filepath of the bytecode file. + -c,--cores Number of cores used in benchmark. + --checker-all Enable all security checkers. + --checker-reentrancy Enable reentrancy checker. + --checker-timestampdependency Enable timestamp-dependency checker. + --checker-txorigin Enable tx-origin checker. + --etherscan-api-key Insert your Etherscan API key. + --link-unsound-jumps-to-all-jumpdest Link all unsound jumps to all jumpdest. + --output-directory-path Filepath of the output directory. + --show-all-instructions-in-cfg Show all instructions in the CFG representation. + --stack-set-size Dimension of stack-set (default: 8). + --stack-size Dimension of stack (default: 32). + --use-live-storage Use the live storage in SLOAD. ``` ## The Abstract Stack Set Domain diff --git a/src/main/java/it/unipr/EVMLiSA.java b/src/main/java/it/unipr/EVMLiSA.java index 5a029a60f..7fa01101e 100644 --- a/src/main/java/it/unipr/EVMLiSA.java +++ b/src/main/java/it/unipr/EVMLiSA.java @@ -810,6 +810,8 @@ private void setupGlobalOptions(CommandLine cmd) { EVMLiSA.setTestMode(); if (cmd.hasOption("paper-stats")) EVMLiSA.setPaperMode(); + if (cmd.hasOption("show-all-instructions-in-cfg")) + DOTFileManager.showAllInstructions(); } private Options getOptions() { @@ -949,6 +951,13 @@ private Options getOptions() { .hasArg(false) .build(); + Option showAllInstructionsInCFG = Option.builder() + .longOpt("show-all-instructions-in-cfg") + .desc("Show all instructions in the Control Flow Graph representation.") + .required(false) + .hasArg(false) + .build(); + options.addOption(addressOption); options.addOption(bytecodeOption); options.addOption(bytecodePathOption); @@ -968,6 +977,7 @@ private Options getOptions() { options.addOption(abiOption); options.addOption(useTestModeOption); options.addOption(usePaperStats); + options.addOption(showAllInstructionsInCFG); return options; } diff --git a/src/main/java/it/unipr/utils/DOTFileManager.java b/src/main/java/it/unipr/utils/DOTFileManager.java index 19dba14de..f475dec27 100644 --- a/src/main/java/it/unipr/utils/DOTFileManager.java +++ b/src/main/java/it/unipr/utils/DOTFileManager.java @@ -20,6 +20,23 @@ public class DOTFileManager { public static String blueColor = "#6FA8DC"; public static String blackColor = "#000000"; + public static boolean showAllInstructions = false; + + /** + * Sets a flag to show all instructions. + */ + public static void showAllInstructions() { + showAllInstructions = true; + } + + /** + * Generates a DOT graph from the provided basic blocks and writes it to the + * specified output path. The graph includes nodes for each basic block, + * edges for outgoing edges, and a legend for color interpretation. + * + * @param basicBlocks an array of JSON objects representing basic blocks + * @param outputPath the file path where the .dot file will be written + */ public static void generateDotGraph(JSONArray basicBlocks, String outputPath) { StringBuilder dotGraph = new StringBuilder(); dotGraph.append("digraph CFG {\n"); @@ -36,7 +53,7 @@ public static void generateDotGraph(JSONArray basicBlocks, String outputPath) { if (block.has("label")) label.append(block.getString("label")).append("\\n- - - - - - - - - - - -\\n"); - if (instructions.length() > 5) { + if (!showAllInstructions && instructions.length() > 5) { JSONObject firstInstr = instructions.getJSONObject(0); JSONObject secondInstr = instructions.getJSONObject(1); JSONObject secondLastInstr = instructions.getJSONObject(instructions.length() - 2);