Repository: angr/angr

Issue:
Result of massive experiment: exception angr.errors.SimFastMemoryError during CFG creation
From the CFG and decompilation experiment across architectures on Debian. Results attached, which have the packages and binaries and exceptions in question.

Attached is a 7zip renamed as a PNG because github doesn't accept xz. Warning: might expand to many gigabytes.
![CFG_FAIL-angr errors SimFastMemoryError xz](https://user-images.githubusercontent.com/3453847/68734752-b3ec5800-0598-11ea-8dac-784f52847c40.png)



Discussion:

Resolving patch:
diff --git a/angr/engines/vex/engine.py b/angr/engines/vex/engine.py
--- a/angr/engines/vex/engine.py
+++ b/angr/engines/vex/engine.py
@@ -389,8 +389,15 @@ def _handle_statement(self, state, successors, stmt):
                 raise UnsupportedIRStmtError("Unsupported statement type %s" % (type(stmt)))
             state.history.add_event('resilience', resilience_type='irstmt', stmt=type(stmt).__name__, message='unsupported IRStmt')
             return None
-        else:
+
+        try:
             exit_data = stmt_handler(self, state, stmt)
+        except SimError as ex:
+            if o.BYPASS_ERRORED_IRSTMT not in state.options:
+                raise ex
+            state.history.add_event('resilience', resilience_type='irstmt', stmt=type(stmt).__name__,
+                                    message='errored IRStmt')
+            return None
 
         # for the exits, put *not* taking the exit on the list of constraints so
         # that we can continue on. Otherwise, add the constraints
diff --git a/angr/sim_options.py b/angr/sim_options.py
--- a/angr/sim_options.py
+++ b/angr/sim_options.py
@@ -214,6 +214,7 @@
 BYPASS_UNSUPPORTED_IRCCALL = "BYPASS_UNSUPPORTED_IRCCALL"
 BYPASS_ERRORED_IRCCALL = "BYPASS_ERRORED_IRCCALL"
 BYPASS_UNSUPPORTED_SYSCALL = "BYPASS_UNSUPPORTED_SYSCALL"
+BYPASS_ERRORED_IRSTMT = "BYPASS_ERRORED_IRSTMT"
 UNSUPPORTED_BYPASS_ZERO_DEFAULT = "UNSUPPORTED_BYPASS_ZERO_DEFAULT"
 
 UNINITIALIZED_ACCESS_AWARENESS = 'UNINITIALIZED_ACCESS_AWARENESS'
@@ -340,7 +341,7 @@
 
 
 # useful sets of options
-resilience = { BYPASS_UNSUPPORTED_IROP, BYPASS_UNSUPPORTED_IREXPR, BYPASS_UNSUPPORTED_IRSTMT, BYPASS_UNSUPPORTED_IRDIRTY, BYPASS_UNSUPPORTED_IRCCALL, BYPASS_ERRORED_IRCCALL, BYPASS_UNSUPPORTED_SYSCALL, BYPASS_ERRORED_IROP, BYPASS_VERITESTING_EXCEPTIONS }
+resilience = { BYPASS_UNSUPPORTED_IROP, BYPASS_UNSUPPORTED_IREXPR, BYPASS_UNSUPPORTED_IRSTMT, BYPASS_UNSUPPORTED_IRDIRTY, BYPASS_UNSUPPORTED_IRCCALL, BYPASS_ERRORED_IRCCALL, BYPASS_UNSUPPORTED_SYSCALL, BYPASS_ERRORED_IROP, BYPASS_VERITESTING_EXCEPTIONS, BYPASS_ERRORED_IRSTMT }
 resilience_options = resilience # alternate name?
 refs = { TRACK_REGISTER_ACTIONS, TRACK_MEMORY_ACTIONS, TRACK_TMP_ACTIONS, TRACK_JMP_ACTIONS, ACTION_DEPS, TRACK_CONSTRAINT_ACTIONS }
 approximation = { APPROXIMATE_SATISFIABILITY, APPROXIMATE_MEMORY_SIZES, APPROXIMATE_MEMORY_INDICES }


Test patch:
diff --git a/tests/test_state.py b/tests/test_state.py
--- a/tests/test_state.py
+++ b/tests/test_state.py
@@ -266,6 +266,38 @@ def test_successors_catch_arbitrary_interrupts():
     nose.tools.assert_equal(len(simgr.unsat), 1)
 
 
+def test_bypass_errored_irstmt():
+
+    # fild [esp+4]  will fail when ftop is unspecified
+    # BYPASS_ERRORED_IRSTMT will suppress it
+
+    block_bytes = b"\xdb\x44\x24\x04"
+
+    proj = angr.load_shellcode(block_bytes, "x86")
+    state = proj.factory.blank_state(addr=0, mode="fastpath", memory_backer=proj.loader.memory,
+                                     add_options={angr.sim_options.FAST_REGISTERS},
+                                     remove_options={angr.sim_options.BYPASS_ERRORED_IRSTMT})
+
+    # destroy esp
+    state.regs._esp = state.solver.BVS("unknown_rsp", 32)
+    state.regs._ftop = state.solver.BVS("unknown_ftop", 32)
+
+    # there should be one errored state if we step the state further without BYPASS_ERRORED_IRSTMT
+    simgr = proj.factory.simgr(state)
+    simgr.step()
+    nose.tools.assert_equal(len(simgr.errored), 1)
+    nose.tools.assert_equal(str(simgr.errored[0].error), "address not supported", msg="Does SimFastMemory support "
+                                                                                      "reading from a symbolic address?")
+
+    # try it with BYPASS_ERRORED_IRSTMT
+    state.options.add(angr.sim_options.BYPASS_ERRORED_IRSTMT)
+    simgr = proj.factory.simgr(state)
+    simgr.step()
+
+    nose.tools.assert_equal(len(simgr.errored), 0)
+    nose.tools.assert_equal(len(simgr.deadended), 1)
+
+
 if __name__ == '__main__':
     test_state()
     test_state_merge()
@@ -276,3 +308,4 @@ def test_successors_catch_arbitrary_interrupts():
     test_state_pickle()
     test_global_condition()
     test_successors_catch_arbitrary_interrupts()
+    test_bypass_errored_irstmt()