Repository: angr/angr

Issue:
CFGFast crashes on libc
When running CFGFast on my libc, angr crashes
[libc-2.29.zip](https://github.com/angr/angr/files/3213257/libc-2.29.zip)

```
p = angr.Project("/usr/lib/libc.so.6")
cfg = p.analyses.cfgfast()

[...]
ERROR   | 2019-05-23 18:27:06,592 | angr.analyses.cfg.cfg_fast | Decoding error occurred at address 0x447ebe of function 0x447d30.
ERROR   | 2019-05-23 18:27:06,593 | angr.analyses.cfg.cfg_fast | Decoding error occurred at address 0x447e99 of function 0x447d30.
ERROR   | 2019-05-23 18:27:06,858 | angr.analyses.cfg.cfg_fast | Decoding error occurred at address 0x4c7b45 of function 0x4c7b30.
WARNING | 2019-05-23 18:27:19,295 | claripy.vsa.strided_interval | Reversing a real strided-interval <64>0x1[0x1, 0xffffffffffffffff]R(uninit) is bad
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-34d0f86d8755> in <module>
----> 1 cfg = p.analyses.CFGFast()

~/Projects/angr-dev/angr/angr/analyses/analysis.py in __call__(self, *args, **kwargs)
    107
    108         oself._show_progressbar = show_progressbar
--> 109         oself.__init__(*args, **kwargs)
    110         return oself
    111

~/Projects/angr-dev/angr/angr/analyses/cfg/cfg_fast.py in __init__(self, binary, objects, regions, pickle_intermediate_results, symbols, function_prologues, resolve_indirect_jumps, force_segment, force_complete_scan, indirect_jump_target_limit, collect_data_references, extra_cross_references, normalize, start_at_entry, function_starts, extra_memory_regions, data_type_guessing_handlers, arch_options, indirect_jump_resolvers, base_state, exclude_sparse_regions, skip_specific_regions, heuristic_plt_resolving, detect_tail_calls, low_priority, cfb, model, start, end, **extra_arch_options)
    624
    625         # Start working!
--> 626         self._analyze()
    627
    628     def __getstate__(self):

~/Projects/angr-dev/angr/angr/analyses/forward_analysis.py in _analyze(self)
    581             # An example is the CFG recovery.
    582
--> 583             self._analysis_core_baremetal()
    584
    585         else:

~/Projects/angr-dev/angr/angr/analyses/forward_analysis.py in _analysis_core_baremetal(self)
    682
    683             if not self._job_info_queue:
--> 684                 self._job_queue_empty()
    685
    686             if not self._job_info_queue:

~/Projects/angr-dev/angr/angr/analyses/cfg/cfg_fast.py in _job_queue_empty(self)
   1104         # Try to see if there is any indirect jump left to be resolved
   1105         if self._resolve_indirect_jumps and self._indirect_jumps_to_resolve:
-> 1106             self._process_unresolved_indirect_jumps()
   1107
   1108             if self._job_info_queue:

~/Projects/angr-dev/angr/angr/analyses/cfg/cfg_base.py in _process_unresolved_indirect_jumps(self)
   2141             if self._low_priority:
   2142                 self._release_gil(idx, 20, 0.0001)
-> 2143             all_targets |= self._process_one_indirect_jump(jump)
   2144
   2145         self._indirect_jumps_to_resolve.clear()

~/Projects/angr-dev/angr/angr/analyses/cfg/cfg_base.py in _process_one_indirect_jump(self, jump)
   2167                 continue
   2168
-> 2169             resolved, targets = resolver.resolve(self, jump.addr, jump.func_addr, block, jump.jumpkind)
   2170             if resolved:
   2171                 resolved_by = resolver

~/Projects/angr-dev/angr/angr/analyses/cfg/indirect_jump_resolvers/jumptable.py in resolve(self, cfg, addr, func_addr, block, jumpkind)
    499                         for target_ in all_targets_copy:
    500                             for lam in invert_conversion_ops:
--> 501                                 target_ = lam(target_)
    502                             all_targets.append(target_)
    503                     mask = (2 ** self.project.arch.bits) - 1

~/Projects/angr-dev/angr/angr/analyses/cfg/indirect_jump_resolvers/jumptable.py in <lambda>(a)
    487                         for conversion_op in conversion_ops:
    488                             if conversion_op is AddressTransferringTypes.SignedExtension32to64:
--> 489                                 lam = lambda a: (a | 0xffffffff00000000) if a >= 0x80000000 else a
    490                             elif conversion_op is AddressTransferringTypes.UnsignedExtension32to64:
    491                                 lam = lambda a: a

TypeError: '>=' not supported between instances of 'NoneType' and 'int'

```




Discussion:

Resolving patch:
diff --git a/angr/analyses/cfg/indirect_jump_resolvers/jumptable.py b/angr/analyses/cfg/indirect_jump_resolvers/jumptable.py
--- a/angr/analyses/cfg/indirect_jump_resolvers/jumptable.py
+++ b/angr/analyses/cfg/indirect_jump_resolvers/jumptable.py
@@ -471,11 +471,18 @@ def resolve(self, cfg, addr, func_addr, block, jumpkind):
                         continue
 
                 # Load the jump table from memory
+                should_skip = False
                 for idx, a in enumerate(state.solver.eval_upto(jumptable_addr, total_cases)):
                     if idx % 100 == 0 and idx != 0:
                         l.debug("%d targets have been resolved for the indirect jump at %#x...", idx, addr)
                     target = cfg._fast_memory_load_pointer(a, size=load_size)
+                    if target is None:
+                        l.debug("Cannot load pointer from address %#x. Skip.", a)
+                        should_skip = True
+                        break
                     all_targets.append(target)
+                if should_skip:
+                    continue
 
                 # Adjust entries inside the jump table
                 if stmts_adding_base_addr:


Test patch: