-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bug: JSONDecodeError crash when running hybrid-echidna
#93
Comments
I had the same issue. I managed to fix it by completely uninstalling nix (https://nix-tutorial.gitlabpages.inria.fr/nix-tutorial/installation.html#uninstalling-nix) and downloading the |
I see what's going on. In https://github.com/crytic/optik/blob/master/optik/echidna/interface.py#L522 optik assumes that The following fix works: --- a/optik/echidna/interface.py
+++ b/optik/echidna/interface.py
@@ -469,7 +469,7 @@ def extract_cases_from_json_output(output: str) -> List[List[str]]:
"""
# Sometimes the JSON output starts with a line such as
# "Loaded total of 500 transactions from /tmp/c4/coverage"
- if output.startswith("Loaded total of"):
+ while output.startswith("Loaded total of"):
output = output.split("\n", 1)[1]
data = json.loads(output)
if "tests" not in data:
@@ -518,7 +518,7 @@ def count_unique_pc(output: str) -> int:
:param output: echidna's JSON output as a simple string
"""
- if output.startswith("Loaded total of"):
+ while output.startswith("Loaded total of"):
output = output.split("\n", 1)[1]
data = json.loads(output)
res = 0 But that's not sufficient to make echidna v2.0.5 work. The json format has also changed so the following dirty fix is needed: --- a/optik/corpus/generator.py
+++ b/optik/corpus/generator.py
@@ -108,10 +108,10 @@ class EchidnaCorpusGenerator(CorpusGenerator):
with open(os.path.join(corpus_dir, filename), "rb") as f:
data = json.loads(f.read())
for tx in data:
- if tx["_call"]["tag"] == "NoCall":
+ if tx["call"]["tag"] == "NoCall":
continue
func_name, args_spec, _ = extract_func_from_call(
- tx["_call"]
+ tx["call"]
)
func_prototype = func_signature(func_name, args_spec)
# Only store one tx for each function
diff --git a/optik/echidna/interface.py b/optik/echidna/interface.py
index ca23622..3f580b8 100644
--- a/optik/echidna/interface.py
+++ b/optik/echidna/interface.py
@@ -168,13 +168,13 @@ def load_tx(tx: Dict, tx_name: str = "") -> AbstractTx:
# Translate block number/timestamp increments
block_num_inc = Var(256, f"{tx_name}_block_num_inc")
block_timestamp_inc = Var(256, f"{tx_name}_block_timestamp_inc")
- ctx.set(block_num_inc.name, int(tx["_delay"][1], 16), block_num_inc.size)
+ ctx.set(block_num_inc.name, int(tx["delay"][1], 16), block_num_inc.size)
ctx.set(
- block_timestamp_inc.name, int(tx["_delay"][0], 16), block_num_inc.size
+ block_timestamp_inc.name, int(tx["delay"][0], 16), block_num_inc.size
)
# Check if it's a "NoCall" echidna transaction
- if tx["_call"]["tag"] == "NoCall":
+ if tx["call"]["tag"] == "NoCall":
return AbstractTx(
None,
block_num_inc,
@@ -183,27 +183,27 @@ def load_tx(tx: Dict, tx_name: str = "") -> AbstractTx:
)
# Translate function call
- func_name, args_spec, arg_values = extract_func_from_call(tx["_call"])
+ func_name, args_spec, arg_values = extract_func_from_call(tx["call"])
call_data = function_call(func_name, args_spec, ctx, tx_name, *arg_values)
# Translate message sender
sender = Var(160, f"{tx_name}_sender")
- ctx.set(sender.name, int(tx["_src"], 16), sender.size)
+ ctx.set(sender.name, int(tx["src"], 16), sender.size)
# Translate message value
# Echidna will only send non-zero msg.value to payable funcs
# so we only make an abstract value in that case
- if int(tx["_value"], 16) != 0:
+ if int(tx["value"], 16) != 0:
value = Var(256, f"{tx_name}_value")
- ctx.set(value.name, int(tx["_value"], 16), value.size)
+ ctx.set(value.name, int(tx["value"], 16), value.size)
else:
value = Cst(256, 0)
# Build transaction
# TODO: make EVMTransaction accept integers as arguments
- gas_limit = Cst(256, int(tx["_gas'"], 16))
- gas_price = Cst(256, int(tx["_gasprice'"], 16))
- recipient = int(tx["_dst"], 16)
+ gas_limit = Cst(256, tx["gas"], 16)
+ gas_price = Cst(256, int(tx["gasprice"], 16))
+ recipient = int(tx["dst"], 16)
return AbstractTx(
EVMTransaction(
sender, # origin
@@ -335,7 +335,7 @@ def update_tx(tx: Dict, new_model: VarContext, tx_name: str = "") -> Dict:
tx = tx.copy() # Copy transaction to avoid in-place modifications
# Update call arguments
- call = tx["_call"]
+ call = tx["call"]
args = call["contents"][1]
for i, arg in enumerate(args):
update_argument(arg, f"{tx_name}_arg{i}", new_model)
@@ -344,20 +344,20 @@ def update_tx(tx: Dict, new_model: VarContext, tx_name: str = "") -> Dict:
block_num_inc = f"{tx_name}_block_num_inc"
block_timestamp_inc = f"{tx_name}_block_timestamp_inc"
if new_model.contains(block_num_inc):
- tx["_delay"][1] = hex(new_model.get(block_num_inc))
+ tx["delay"][1] = hex(new_model.get(block_num_inc))
if new_model.contains(block_timestamp_inc):
- tx["_delay"][0] = hex(new_model.get(block_timestamp_inc))
+ tx["delay"][0] = hex(new_model.get(block_timestamp_inc))
# Update sender
sender = f"{tx_name}_sender"
if new_model.contains(sender):
# Address so we need to pad it to 40 chars (20bytes)
- tx["_src"] = f"0x{new_model.get(sender):0{40}x}"
+ tx["src"] = f"0x{new_model.get(sender):0{40}x}"
# Update transaction value
value = f"{tx_name}_value"
if new_model.contains(value):
- tx["_value"] = hex(new_model.get(value))
+ tx["value"] = hex(new_model.get(value))
return tx I will let someone more knowledgeable identify and implement a proper solution. |
Describe the bug
It runs
echidna
for about 2 minutes and then crashes.To Reproduce
Sadly I cannot share my environment. I could narrowing things down with some guidance.
Additional context:
The text was updated successfully, but these errors were encountered: