Source code for angr.analyses.reaching_definitions.heap_allocator
import logging
from typing import Union, List
from ...knowledge_plugins.key_definitions.heap_address import HeapAddress
from ...knowledge_plugins.key_definitions.unknown_size import UnknownSize
from ...knowledge_plugins.key_definitions.undefined import Undefined
_l = logging.getLogger(name=__name__)
[docs]class HeapAllocator:
"""
A simple modelisation to help represent heap memory management during a <ReachingDefinitionsAnalysis>:
- Act as if allocations were always done in consecutive memory segments;
- Take care of the size not to screw potential pointer arithmetic (avoid overlapping segments).
The content of the heap itself is modeled using a <KeyedRegion> attribute in the <LiveDefinitions> state;
This class serves to generate consistent heap addresses to be used by the aforementionned.
*Note:* This has **NOT** been made to help detect heap vulnerabilities.
"""
[docs] def __init__(self, canonical_size: int):
"""
:param canonical_size: The concrete size an <UNKNOWN_SIZE> defaults to.
"""
self._next_heap_address: HeapAddress = HeapAddress(0)
self._allocated_addresses: List[HeapAddress] = [self._next_heap_address]
self._canonical_size: int = canonical_size
[docs] def allocate(self, size: Union[int, UnknownSize]) -> HeapAddress:
"""
Gives an address for a new memory chunck of <size> bytes.
:param size: The requested size for the chunck, in number of bytes.
:return: The address of the chunck.
"""
address = self._next_heap_address
size = self._canonical_size if isinstance(size, UnknownSize) else size
self._next_heap_address += size
self._allocated_addresses += [self._next_heap_address]
return address
[docs] def free(self, address: Union[Undefined, HeapAddress]):
"""
Mark the chunck pointed by <address> as freed.
:param address: The address of the chunck to free.
"""
if isinstance(address, Undefined):
_l.debug("free(), Undefined address provided")
elif isinstance(address, HeapAddress):
try:
self._allocated_addresses.remove(address)
except ValueError:
_l.warning("free(), address %s had not been allocated", address)
else:
_l.warning("free(), expected HeapAddress, or Undefined, got %s", type(address).__name__)
@property
def allocated_addresses(self):
"""
:return: The list of addresses that are currently allocated on the heap.
"""
return self._allocated_addresses