Fix issues with statespace on solc 0.8.26 (#1863)

* Fix issues with statespace on solc 0.8.26

* Sort the import
develop
Nikhil Parasaram 3 months ago committed by GitHub
parent ea60b14c99
commit 8201bfd75f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 46
      mythril/analysis/callgraph.py
  2. 36
      mythril/laser/ethereum/cfg.py

@ -2,6 +2,7 @@
graphs.""" graphs."""
import re import re
from typing import Dict, List
from jinja2 import Environment, PackageLoader, select_autoescape from jinja2 import Environment, PackageLoader, select_autoescape
from z3 import Z3Exception from z3 import Z3Exception
@ -125,56 +126,52 @@ phrack_color = {
} }
def extract_nodes(statespace): def extract_nodes(statespace) -> List[Dict]:
""" """
Extract nodes from the given statespace and create a list of node dictionaries
with visual attributes for graph representation.
:param statespace: :param statespace: The statespace object containing nodes and states information.
:param color_map: :return: A list of dictionaries representing each node with its attributes.
:return:
""" """
nodes = [] nodes = []
color_map = {} color_map = {}
for node_key in statespace.nodes: for node_key, node in statespace.nodes.items():
node = statespace.nodes[node_key]
instructions = [state.get_current_instruction() for state in node.states] instructions = [state.get_current_instruction() for state in node.states]
code_split = [] code_split = []
for instruction in instructions: for instruction in instructions:
if instruction["opcode"].startswith("PUSH"): address = instruction["address"]
code_line = "%d %s %s" % ( opcode = instruction["opcode"]
instruction["address"], if opcode.startswith("PUSH"):
instruction["opcode"], code_line = f"{address} {opcode} {instruction.get('argument', '')}"
instruction["argument"],
)
elif ( elif (
instruction["opcode"].startswith("JUMPDEST") opcode.startswith("JUMPDEST")
and NodeFlags.FUNC_ENTRY in node.flags and NodeFlags.FUNC_ENTRY in node.flags
and instruction["address"] == node.start_addr and address == node.start_addr
): ):
code_line = node.function_name code_line = node.function_name
else: else:
code_line = "%d %s" % (instruction["address"], instruction["opcode"]) code_line = f"{address} {opcode}"
code_line = re.sub( code_line = re.sub(r"([0-9a-f]{8})[0-9a-f]+", r"\1(...)", code_line)
"([0-9a-f]{8})[0-9a-f]+", lambda m: m.group(1) + "(...)", code_line
)
code_split.append(code_line) code_split.append(code_line)
truncated_code = ( truncated_code = (
"\n".join(code_split) "\n".join(code_split)
if (len(code_split) < 7) if len(code_split) < 7
else "\n".join(code_split[:6]) + "\n(click to expand +)" else "\n".join(code_split[:6]) + "\n(click to expand +)"
) )
if node.get_cfg_dict()["contract_name"] not in color_map.keys(): contract_name = node.get_cfg_dict()["contract_name"]
if contract_name not in color_map:
color = default_colors[len(color_map) % len(default_colors)] color = default_colors[len(color_map) % len(default_colors)]
color_map[node.get_cfg_dict()["contract_name"]] = color color_map[contract_name] = color
nodes.append( nodes.append(
{ {
"id": str(node_key), "id": str(node_key),
"color": color_map.get( "color": color_map.get(contract_name, default_colors[0]),
node.get_cfg_dict()["contract_name"], default_colors[0]
),
"size": 150, "size": 150,
"fullLabel": "\n".join(code_split), "fullLabel": "\n".join(code_split),
"label": truncated_code, "label": truncated_code,
@ -182,6 +179,7 @@ def extract_nodes(statespace):
"isExpanded": False, "isExpanded": False,
} }
) )
return nodes return nodes

@ -59,25 +59,29 @@ class Node:
def get_cfg_dict(self) -> Dict: def get_cfg_dict(self) -> Dict:
""" """
Generate a configuration dictionary for the current state of the contract.
:return: :return: A dictionary containing the contract's configuration details.
""" """
code = "" code_lines = [
for state in self.states: f"{instruction['address']} {instruction['opcode']}"
instruction = state.get_current_instruction() + (
f" {instruction['argument']}"
code += str(instruction["address"]) + " " + instruction["opcode"] if instruction["opcode"].startswith("PUSH")
if instruction["opcode"].startswith("PUSH"): and "argument" in instruction
code += " " + "".join(str(instruction["argument"])) else ""
code += "\\n"
return dict(
contract_name=self.contract_name,
start_addr=self.start_addr,
function_name=self.function_name,
code=code,
) )
for state in self.states
for instruction in [state.get_current_instruction()]
]
code = "\\n".join(code_lines)
return {
"contract_name": self.contract_name,
"start_addr": self.start_addr,
"function_name": self.function_name,
"code": code,
}
class Edge: class Edge:

Loading…
Cancel
Save