Overview
Heap regions are commonly where data corruption causes system failures. As OS_Heap
is entirely under the control
of the RISC OS Pyromaniac system, it has been extended to allow more diagnostics when problems occur, and better
defaults. The configuration also allows greater control over the invariants from the original heap, but keeps to
the RISC OS Classic allocation system for compatibility.
Dynamic Area Heaps are a fully managed allocation region. As such, they have more diagnostics features, and can
detect corruption and misuse more easily than the standard OS_Heap
regions. This includes guard words to detect
over and underruns, and protection for regions of the heap.
These options should help to find the cause of failures by detecting them with increasing costs in speed.
OS_Heap regions
Clearing regions
The OS_Heap can be configured to clear regions when they are allocated, and when they are freed. This ensures that use-after-free will result in unexpected (usually fatal) behaviour which can be corrected. By default, this feature is disabled, but the can be enabled independantly for allocation and free.
heap.clear_alloc_enable
- enables the clearing of the allocated regions of memory using a constant configured by the optionheap.clear_alloc_value
. This defaults to&a110ced3
. This is a stylised 'alloced' , with both bit 0 and 1 set to ensure that if used as a word this value will be unaligned.heap.clear_free_enable
- enables the clearing of the freed regions of memory using a constant configured by the optionheap.clear_free_value
. This detaults to&f0f1f2f3
. This is intended to invoke the idea that it is free, whilst not looking like an obvious negative number. As with the allocation, both bit 0 and 1 are set.
For example, with these options enabled, reusing a region of unintialised or freed memory may cause a Data Abort.
Printing a pointer from a region of freed memory may produce a stream of óòñð
characters (when the alphabet is
set to Latin 1), which should be recognisable.
Block alignment and limits
The OS_Heap
regions can be rounded to blocks of a known size. This allows testing of the behaviour when assumptions
have been made about the actual size of allocations (as opposed to the requested size). Similarly, the minimum block
allocation size can be configured.
heap.rounding
- controls the number of bytes that the allocation size will be rounded to before allocating the block.heap.minimum_allocation
- limits the minimum size of the block
The behaviour of a block extension to 0 (or smaller) is able to be configured to report an error. On RISC OS Classic this operation would return a pointer of -1, without error.
heap.extend_to_nothing_is_error
- controls whether an error is returned.
Heaps as a whole can be restricted in size, which may detect some oversized heaps, or heap header corruption for applications.
heap.maximum_heap_size
- configures the limit on the size of the heap.
The standard OS_Heap
will interfaces will report errors if the heap is found to be corrupted. This may include
trace reports which include information about the call stack in C programs, when the corruption is detected. As
corruption can only be detected within calls to OS_Heap
, problems may be reported long after they were introduced.
Dynamic Area Heaps
Dynamic Area heaps are persistent managed memory allocation regions, and so can have greater diagnostic abilities.
This applies to the System Heap and the Relocatable Module Area. In particular, this means that the OS_Module
calls to allocate, free and extend memory blocks has greater facilities available to it.
Administrative area protection
The header word on allocated blocks, and the words used for freed blocks may be protected as a separate watchpoint region. This means that they can be configured to perform different operations on access. This may detect heap misuse and overflows.
watchregions.daheap
- may be set to a configuration value to detect the misuse of regions within the Dynamic Area heap. The values that may be commonly useful might be to make writes to the watched regions cause a trace event to be triggered (write=trace
, or justwrite
), or to make writes to the watched regions cause a data abort (write=abort
). It is also possible to trace reads of these protected blocks (read
orread=trace
), or to make reads trace, and writes abort (yes=abort-on-write
).
Enabling the watch regions for Dynamic area heaps will slow the system down considerably as these regions will be checked on each data access, and may cause a large number of slow operations. This may detect overflow writes in the heap, where they have become a problem, although remember tha the heap allocations have a minimum size and will be rounded up if necessary; this may mean that the actual allocation of the heap block is larger than requested.
Guard words
Allocations (and frees) within the heap can be given a 'guard' region before and after the allocated block. This region is assigned a constant value, and can be checked when the allocation and free operations are performed. If the guard value is found to have been changed, an error can be triggered.
dynamicareaheap.guard_size
- configures the number of bytes used for the guard region. If this is set to 0, no guard region is provided.dynamicareaheap.guard_alloc_value
- the value used within the allocated block's guard region. This defaults to&81818181
which is hopefully recognisable, and should cause an abort if used as a pointer.dynamicareaheap.guard_free_value
- the value used within the freed block's guard region. This defaults to&82828282
which is hopefully recognisable, and should cause an abort if used as a pointer.
If the watch regions for Dynamic Area heaps are enabled, they will include the guard regions. This means that overflow and underflow of the blocks may be detected much more quickly, without corrupting the heap itself.
Tracked heap blocks
The heap block allocations may be tracked by the system. This means that on allocation the block remembers who made the call to allocate it, as best as can be determined from the call stack. These allocations can be reported when corruption or other failures are detected. This is the current default.
dynamicareaheap.tracking_full_checks
- enables checking of heap blocks on every allocation and free.