Repository: angr/angr

Issue:
AttributeError: 'DefaultMemory' object has no attribute '_unconstrained_range'


**Describe the bug.**

Symbolic Execution crashes deeps inside the memory mixins with `AttributeError: 'DefaultMemory' object has no attribute '_unconstrained_range'`

This is fairly confusing because this happens inside the `UnderconstrainedMixin` which obviously defines `_unconstrained_range` in its constructor, yet, I can confirm with a debugger that I can end up in the crashing line with a `DefaultMemory` object that doesn't. My best guess is that under some circumstances the constructor for `UnderconstrainedMixin` isn't called. I can't properly confirm this though, the initial states generated for the exploration have `DefaultMemory` objects with `_unconstrained_range` initialized as expected.

Nearly all Mixins I checked don't even have a constructor, and for the `UnderconstrainedMixin` the value isn't even an argument, so it could be changed to a class variable as a workaround if this is indeed the case that for some reason the constructor isn't called. 


```
Traceback (most recent call last):
  [...]
  File "/home/fmagin/Projects/angr-dev/angr/angr/sim_state.py", line 587, in step
    return self.project.factory.successors(self, **kwargs)
  File "/home/fmagin/Projects/angr-dev/angr/angr/factory.py", line 60, in successors
    return self.default_engine.process(*args, **kwargs)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/vex/light/slicing.py", line 19, in process
    return super().process(*args, **kwargs)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/engine.py", line 149, in process
    self.process_successors(self.successors, **kwargs)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/failure.py", line 21, in process_successors
    return super().process_successors(successors, **kwargs)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/syscall.py", line 18, in process_successors
    return super().process_successors(successors, **kwargs)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/hook.py", line 54, in process_successors
    return super().process_successors(successors, procedure=procedure, **kwargs)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/unicorn.py", line 169, in process_successors
    return super().process_successors(successors, **kwargs)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/soot/engine.py", line 64, in process_successors
    return super().process_successors(successors, **kwargs)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/vex/heavy/heavy.py", line 138, in process_successors
    self.handle_vex_block(irsb)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/vex/heavy/super_fastpath.py", line 19, in handle_vex_block
    super().handle_vex_block(irsb)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/vex/light/slicing.py", line 26, in handle_vex_block
    super().handle_vex_block(irsb)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/vex/heavy/actions.py", line 30, in handle_vex_block
    super().handle_vex_block(irsb)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/vex/heavy/inspect.py", line 45, in handle_vex_block
    super().handle_vex_block(irsb)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/vex/light/light.py", line 446, in handle_vex_block
    self._handle_vex_stmt(stmt)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/vex/light/slicing.py", line 30, in _handle_vex_stmt
    super()._handle_vex_stmt(stmt)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/vex/heavy/inspect.py", line 40, in _handle_vex_stmt
    super()._handle_vex_stmt(stmt)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/vex/light/resilience.py", line 36, in inner
    return getattr(super(VEXResilienceMixin, self), func)(*iargs, **ikwargs)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/vex/heavy/heavy.py", line 204, in _handle_vex_stmt
    super()._handle_vex_stmt(stmt)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/vex/light/light.py", line 51, in _handle_vex_stmt
    handler(stmt)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/vex/light/light.py", line 196, in _handle_vex_stmt_Store
    self._perform_vex_stmt_Store(
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/vex/heavy/actions.py", line 177, in _perform_vex_stmt_Store
    super()._perform_vex_stmt_Store(addr, data, end, action=a, condition=condition, **kwargs)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/vex/claripy/datalayer.py", line 93, in _perform_vex_stmt_Store
    super()._perform_vex_stmt_Store(addr, data.raw_to_bv(), endness, **kwargs)
  File "/home/fmagin/Projects/angr-dev/angr/angr/engines/vex/heavy/heavy.py", line 35, in _perform_vex_stmt_Store
    self.state.memory.store(addr, data, endness=endness, action=action, inspect=inspect, condition=condition)
  File "/home/fmagin/Projects/angr-dev/angr/angr/storage/memory_mixins/unwrapper_mixin.py", line 8, in store
    return super().store(_raw_ast(addr), _raw_ast(data),
  File "/home/fmagin/Projects/angr-dev/angr/angr/storage/memory_mixins/name_resolution_mixin.py", line 50, in store
    return super().store(addr, data, size=size, **kwargs)
  File "/home/fmagin/Projects/angr-dev/angr/angr/storage/memory_mixins/bvv_conversion_mixin.py", line 25, in store
    super().store(addr, data_bv, size=size, **kwargs)
  File "/home/fmagin/Projects/angr-dev/angr/angr/storage/memory_mixins/simplification_mixin.py", line 11, in store
    super().store(addr, real_data, **kwargs)
  File "/home/fmagin/Projects/angr-dev/angr/angr/storage/memory_mixins/clouseau_mixin.py", line 6, in store
    super().store(addr, data,
  File "/home/fmagin/Projects/angr-dev/angr/angr/storage/memory_mixins/actions_mixin.py", line 34, in store
    super().store(addr, data, size=size, action=action, condition=condition, **kwargs)
  File "/home/fmagin/Projects/angr-dev/angr/angr/storage/memory_mixins/underconstrained_mixin.py", line 20, in store
    self._constrain_underconstrained_index(addr)
  File "/home/fmagin/Projects/angr-dev/angr/angr/storage/memory_mixins/underconstrained_mixin.py", line 41, in _constrain_underconstrained_index
    if not self.state.uc_manager.is_bounded(addr) or self.state.solver.max_int(addr) - self.state.solver.min_int(addr) >= self._unconstrained_range:
AttributeError: 'DefaultMemory' object has no attribute '_unconstrained_range'
```


**Environment Information.**
```
angr environment report
=============================
Date: 2021-06-27 15:28:23.293361
Running in virtual environment at /home/fmagin/.virtualenvs/sit-angr-analysis-service
Platform: linux-x86_64
Python version: 3.9.5 (default, May 24 2021, 12:50:35) 
[GCC 11.1.0]
######## angr #########
Python found it in /home/fmagin/Projects/angr-dev/angr/angr
Pip version angr 9.0.gitrolling
Git info:
	Current commit 92f8167e7823d1e88dbb72ed8f716b0fc863cbd9 from branch master
	Checked out from remote origin: https://github.com/angr/angr.git
######## ailment #########
Python found it in /home/fmagin/Projects/angr-dev/ailment/ailment
Pip version ailment 9.0.gitrolling
Git info:
	Current commit 9c3abc9a226f2f3fdca5f56a22d8bd694d2035b4 from branch master
	Checked out from remote origin: https://github.com/angr/ailment.git
######## cle #########
Python found it in /home/fmagin/Projects/angr-dev/cle/cle
Pip version cle 9.0.gitrolling
Git info:
	Current commit d7d80cf4f4a8f7bafb257c17190ea89ab2abaa50 from branch master
	Checked out from remote origin: https://github.com/angr/cle.git
######## pyvex #########
Python found it in /home/fmagin/Projects/angr-dev/pyvex/pyvex
Pip version pyvex 9.0.gitrolling
Git info:
	Current commit b7006517fcb9fcd713b070315b7c18277c942113 from branch master
	Checked out from remote origin: https://github.com/angr/pyvex.git
######## claripy #########
Python found it in /home/fmagin/Projects/angr-dev/claripy/claripy
Pip version claripy 9.0.gitrolling
Git info:
	Current commit d372dd28bede388d44c018b06168239ca335329a from branch master
	Checked out from remote origin: https://github.com/angr/claripy.git
######## archinfo #########
Python found it in /home/fmagin/Projects/angr-dev/archinfo/archinfo
Pip version archinfo 9.0.gitrolling
Git info:
	Current commit b150db4c0a939140966df8b0056b6deb5b07efbf from branch master
	Checked out from remote origin: https://github.com/angr/archinfo.git
######## z3 #########
Python found it in /home/fmagin/.virtualenvs/sit-angr-analysis-service/lib/python3.9/site-packages/z3
Pip version z3-solver 4.8.10.0
Couldn't find git info
######## unicorn #########
Python found it in /home/fmagin/.virtualenvs/sit-angr-analysis-service/lib/python3.9/site-packages/unicorn
Pip version unicorn 1.0.2rc4
Couldn't find git info
######### Native Module Info ##########
angr: <CDLL '/home/fmagin/Projects/angr-dev/angr/angr/lib/angr_native.so', handle 55dc453581c0 at 0x7f9c3fe6c670>
unicorn: <CDLL '/home/fmagin/.virtualenvs/sit-angr-analysis-service/lib/python3.9/site-packages/unicorn/lib/libunicorn.so', handle 55dc44aa1660 at 0x7f9c4559bc40>
pyvex: <cffi.api._make_ffi_library.<locals>.FFILibrary object at 0x7f9c4610a070>
z3: <CDLL '/home/fmagin/.virtualenvs/sit-angr-analysis-service/lib/python3.9/site-packages/z3/lib/libz3.so', handle 55dc44cd3620 at 0x7f9c430f7b80>
```


**To Reproduce.**

Not sure what the minimal PoC for this is, will share one if I can find a simple trigger, but at that point I might have found the solution already anyway.



Discussion:
By any chance is there pickle serialization going on, either explicitly or through IPC?
Nope, it's pretty much just a call to simgr.run() with some custom exploration and filter.
If you have some suggestion how to most easily find out if a DefaultMemory object is created without the UnderConstrainedMixin constructor being called, I can run that tomorrow, the issue consistently reproduces in our full setup.

Resolving patch:
diff --git a/angr/storage/memory_mixins/underconstrained_mixin.py b/angr/storage/memory_mixins/underconstrained_mixin.py
--- a/angr/storage/memory_mixins/underconstrained_mixin.py
+++ b/angr/storage/memory_mixins/underconstrained_mixin.py
@@ -12,6 +12,12 @@ def __init__(self, *args, **kwargs):
 
         self._unconstrained_range = 1024
 
+    @MemoryMixin.memo
+    def copy(self, memo):
+        out = super().copy(memo)
+        out._unconstrained_range = self._unconstrained_range
+        return out
+
     def load(self, addr, **kwargs):
         self._constrain_underconstrained_index(addr)
         return super().load(addr, **kwargs)
@@ -46,4 +52,3 @@ def _constrain_underconstrained_index(self, addr):
                 if self.state.solver.solution(addr, mem_region):
                     self.state.add_constraints(addr == mem_region)
                 l.debug('Under-constrained symbolic execution: assigned a new memory region @ %s to %s', mem_region, addr)
-


Test patch: