rlib
Convenience library for useful things
Loading...
Searching...
No Matches
Memory

Heap / stack allocators, byte-buffer operations, and pattern-based memory scanning. More...

Modules

 Buffers
 Refcounted byte container that holds an ordered list of RMem chunks.
 
 Refcounted memory chunks and pluggable allocators
 Abstract memory-chunk type (RMem) with a pluggable backend (RMemAllocator). Inspired by GStreamer's GstMemory / GstAllocator design.
 
 Memory-mapped file regions
 Map a whole file (or an open file handle) into the process address space as a single contiguous byte buffer.
 
 Inline byte-buffer primitives
 Inline memcmp / memcpy / memmove / memset wrappers with rlib's NULL-tolerant convention.
 

Files

file  rmem.h
 Memory allocation, byte-buffer operations, and pattern scanning.
 

Data Structures

struct  RMemChunk
 Pointer + length view of a memory region. More...
 
struct  RMemVTable
 Allocator backend slots routed through by every rlib heap helper. More...
 
struct  RMemScanToken
 One token of a parsed scan pattern. More...
 
struct  RMemScanResult
 Result of a successful r_mem_scan_pattern call. More...
 

Macros

#define r_alloca(size)   alloca (size)
 Allocate size bytes on the stack frame of the caller.
 
#define r_alloca0(size)   r_memclear (r_alloca (size), size)
 Stack-allocate size bytes and zero-fill them.
 
#define r_mem_newa_n(type, n)   ((type*) r_alloca (sizeof (type) * (rsize) (n)))
 Stack-allocate an array of n elements of type.
 
#define r_mem_newa0_n(type, n)   ((type*) r_alloca0 (sizeof (type) * (rsize) (n)))
 Stack-allocate a zeroed array of n elements of type.
 
#define r_mem_newa(type)   r_mem_newa_n (type, 1)
 Stack-allocate a single instance of type.
 
#define r_mem_newa0(type)   r_mem_newa0_n (type, 1)
 Stack-allocate a single zeroed instance of type.
 
#define r_mem_new_n(type, n)   ((type*) r_malloc (sizeof (type) * (rsize) (n)))
 Allocate an array of n elements of type.
 
#define r_mem_new0_n(type, n)   ((type*) r_malloc0 (sizeof (type) * (rsize) (n)))
 Allocate a zeroed array of n elements of type.
 
#define r_mem_new(type)   r_mem_new_n (type, 1)
 Allocate a single instance of type.
 
#define r_mem_new0(type)   r_mem_new0_n (type, 1)
 Allocate a single zeroed instance of type.
 

Enumerations

enum  RMemTokenType {
  R_MEM_TOKEN_NONE = -1 , R_MEM_TOKEN_BYTES , R_MEM_TOKEN_WILDCARD , R_MEM_TOKEN_WILDCARD_SIZED ,
  R_MEM_TOKEN_COUNT
}
 Token classes produced by the r_mem_scan_pattern parser. More...
 
enum  RMemScanResultType {
  R_MEM_SCAN_RESULT_INVAL = -4 , R_MEM_SCAN_RESULT_OOM = -3 , R_MEM_SCAN_RESULT_INVALID_PATTERN = -2 , R_MEM_SCAN_RESULT_PATTERN_NOT_IMPL = -1 ,
  R_MEM_SCAN_RESULT_OK = 0 , R_MEM_SCAN_RESULT_NOT_FOUND
}
 Status codes returned by r_mem_scan_pattern. More...
 

Functions

char * alloca ()
 
void r_free (rpointer ptr)
 Release a heap allocation obtained from r_malloc / r_malloc0 / r_calloc / r_realloc.
 
rpointer r_malloc (rsize size) R_ATTR_ALLOC_SIZE_ARG(1)
 Allocate size uninitialised bytes on the heap.
 
rpointer r_malloc0 (rsize size) R_ATTR_ALLOC_SIZE_ARG(1)
 Allocate size zero-initialised bytes on the heap.
 
rpointer r_calloc (rsize count, rsize size) R_ATTR_ALLOC_SIZE_ARGS(1
 Allocate count zero-initialised elements of size bytes.
 
rpointer rpointer r_realloc (rpointer ptr, rsize size) R_ATTR_WARN_UNUSED_RESULT
 Resize an existing allocation to size bytes.
 
void r_mem_set_vtable (RMemVTable *vtable)
 Replace the active allocator vtable.
 
void r_mem_get_vtable (RMemVTable *out)
 Copy the active vtable into *out.
 
rboolean r_mem_using_system_default (void)
 Whether the active vtable still points at libc.
 
int r_memcmp_ct (rconstpointer a, rconstpointer b, rsize size)
 Constant-time variant of r_memcmp.
 
void r_memclear_secure (rpointer ptr, rsize size)
 Zero size bytes at ptr in a way the compiler can't elide.
 
rpointer r_memdup (rconstpointer src, rsize size)
 Heap-allocate a copy of size bytes at src.
 
rsize r_memagg (rpointer dst, rsize size, rsize *out,...)
 Aggregate (concatenate) a NULL-terminated list of byte chunks into dst.
 
rsize r_memaggv (rpointer dst, rsize size, rsize *out, va_list args)
 va_list variant of r_memagg.
 
rpointer r_memdup_agg (rsize *out,...)
 Aggregate a NULL-terminated list of byte chunks into a freshly-allocated buffer.
 
rpointer r_memdup_aggv (rsize *out, va_list args)
 va_list variant of r_memdup_agg.
 
rpointer r_mem_scan_byte (rconstpointer mem, rsize size, ruint8 byte)
 Find the first occurrence of byte byte in mem.
 
rpointer r_mem_scan_byte_any (rconstpointer mem, rsize size, const ruint8 *byte, rsize bytes)
 Find the first byte in mem that matches any byte in the byte set.
 
rpointer r_mem_scan_data (rconstpointer mem, rsize size, rconstpointer data, rsize datasize)
 Find the first occurrence of datasize-byte sequence data within mem.
 
rpointer r_mem_scan_simple_pattern (rconstpointer mem, rsize size, const rchar *pattern, rpointer *end)
 Find the first match for pattern in mem (simple form).
 
RMemScanResultType r_mem_scan_pattern (rconstpointer mem, rsize size, const rchar *pattern, RMemScanResult **result)
 Find the first match for pattern in mem, returning full per-token detail.
 

Detailed Description

Heap / stack allocators, byte-buffer operations, and pattern-based memory scanning.

Macro Definition Documentation

◆ r_alloca

#define r_alloca (   size)    alloca (size)

Allocate size bytes on the stack frame of the caller.

Thin portability shim around alloca / _alloca / __builtin_alloca. Storage lives until the enclosing function returns; do not return or hand the pointer to code outside the caller's lifetime.

Parameters
sizeNumber of bytes (typically a small constant - large requests risk stack overflow).

Enumeration Type Documentation

◆ RMemScanResultType

Status codes returned by r_mem_scan_pattern.

Enumerator
R_MEM_SCAN_RESULT_INVAL 

NULL mem / pattern / result.

R_MEM_SCAN_RESULT_OOM 

Allocator returned NULL for the result struct.

R_MEM_SCAN_RESULT_INVALID_PATTERN 

Pattern failed to parse.

R_MEM_SCAN_RESULT_PATTERN_NOT_IMPL 

Pattern uses a feature not supported by this build.

R_MEM_SCAN_RESULT_OK 

Match found; *result populated.

R_MEM_SCAN_RESULT_NOT_FOUND 

Parsed cleanly, no match in mem.

◆ RMemTokenType

Token classes produced by the r_mem_scan_pattern parser.

The pattern grammar reads as ASCII tokens separated by whitespace:

  • "AA" hex pair → R_MEM_TOKEN_BYTES (run of literal bytes)
  • "??"R_MEM_TOKEN_WILDCARD_SIZED (run of N wildcard bytes)
  • "*"R_MEM_TOKEN_WILDCARD (variable-length wildcard)
Enumerator
R_MEM_TOKEN_NONE 

Pattern terminator / parse error.

R_MEM_TOKEN_BYTES 

Literal byte run (one or more hex pairs).

R_MEM_TOKEN_WILDCARD 

Variable-length wildcard (*).

R_MEM_TOKEN_WILDCARD_SIZED 

Fixed-length wildcard (run of ??).

Function Documentation

◆ r_calloc()

rpointer r_calloc ( rsize  count,
rsize  size 
)

Allocate count zero-initialised elements of size bytes.

Mirrors libc calloc semantics: the allocation is zeroed and count * size is computed with overflow checking by the underlying allocator.

Parameters
countNumber of elements.
sizeSize of each element in bytes.
Returns
Allocation pointer, or NULL on failure.

◆ r_free()

void r_free ( rpointer  ptr)

Release a heap allocation obtained from r_malloc / r_malloc0 / r_calloc / r_realloc.

Routes through the currently-installed RMemVTable. A NULL ptr is a no-op (matches libc free).

Parameters
ptrAllocation to release.

◆ r_malloc()

rpointer r_malloc ( rsize  size)

Allocate size uninitialised bytes on the heap.

Routes through the currently-installed RMemVTable.

Parameters
sizeNumber of bytes (zero is implementation-defined).
Returns
Allocation pointer, or NULL on failure.

◆ r_malloc0()

rpointer r_malloc0 ( rsize  size)

Allocate size zero-initialised bytes on the heap.

Implemented as calloc(1, size) through the active vtable.

Parameters
sizeNumber of bytes.
Returns
Allocation pointer, or NULL on failure.

◆ r_mem_get_vtable()

void r_mem_get_vtable ( RMemVTable out)

Copy the active vtable into *out.

Pairs with r_mem_set_vtable so a caller (typically a test) can save the active vtable, swap in its own, then restore exactly the pointers it saw. Restoring via r_mem_set_vtable with locally- typed { malloc, calloc, realloc, free } is not safe across DLL boundaries on Windows - the test binary's import thunks resolve to different addresses than the rlib DLL's.

Parameters
outDestination vtable (must be non-NULL).

◆ r_mem_scan_byte()

rpointer r_mem_scan_byte ( rconstpointer  mem,
rsize  size,
ruint8  byte 
)

Find the first occurrence of byte byte in mem.

Equivalent in semantics to memchr but with rlib's NULL-tolerant convention.

Parameters
memMemory region (may be NULL).
sizeRegion length in bytes.
byteByte to search for.
Returns
Pointer to the first match, or NULL if not found (or mem is NULL).

◆ r_mem_scan_byte_any()

rpointer r_mem_scan_byte_any ( rconstpointer  mem,
rsize  size,
const ruint8 byte,
rsize  bytes 
)

Find the first byte in mem that matches any byte in the byte set.

Parameters
memMemory region (may be NULL).
sizeRegion length in bytes.
byteSet of bytes to match (may be NULL).
bytesNumber of bytes in byte.
Returns
Pointer to the first match, or NULL.

◆ r_mem_scan_data()

rpointer r_mem_scan_data ( rconstpointer  mem,
rsize  size,
rconstpointer  data,
rsize  datasize 
)

Find the first occurrence of datasize-byte sequence data within mem.

Naive byte-at-a-time search anchored on the first byte of data; suitable for small needles. For pattern matching with wildcards use r_mem_scan_pattern.

Parameters
memHaystack (may be NULL).
sizeHaystack length in bytes.
dataNeedle bytes (may be NULL).
datasizeNeedle length in bytes.
Returns
Pointer to the first match within mem, or NULL.

◆ r_mem_scan_pattern()

RMemScanResultType r_mem_scan_pattern ( rconstpointer  mem,
rsize  size,
const rchar pattern,
RMemScanResult **  result 
)

Find the first match for pattern in mem, returning full per-token detail.

Allocates an RMemScanResult sized to the parsed token count; the caller releases it with r_free. See RMemTokenType for the pattern grammar.

Parameters
memHaystack (must be non-NULL).
sizeHaystack length in bytes.
patternNUL-terminated pattern string (must be non-NULL).
resultReceives the freshly-allocated result struct (must be non-NULL). Set to NULL if no allocation was attempted.
Returns
R_MEM_SCAN_RESULT_OK on match, R_MEM_SCAN_RESULT_NOT_FOUND if the pattern parsed but didn't match, a negative RMemScanResultType code on error.

◆ r_mem_scan_simple_pattern()

rpointer r_mem_scan_simple_pattern ( rconstpointer  mem,
rsize  size,
const rchar pattern,
rpointer end 
)

Find the first match for pattern in mem (simple form).

Wraps r_mem_scan_pattern for the common case where the caller only wants the match start (and optionally end) and doesn't need the per-token breakdown.

Parameters
memHaystack.
sizeHaystack length in bytes.
patternNUL-terminated pattern string.
endIf non-NULL, receives one past the last byte of the match.
Returns
Pointer to the first byte of the match, or NULL on no match / parse error / OOM.

◆ r_mem_set_vtable()

void r_mem_set_vtable ( RMemVTable vtable)

Replace the active allocator vtable.

Every subsequent r_malloc / r_calloc / r_realloc / r_free call routes through the new slots. Intended to be called once at process start; switching mid-flight risks freeing a pointer with a different backend than the one that allocated it.

A NULL vtable, or a vtable with any NULL slot, is rejected (the active vtable is left untouched). This catches the otherwise- common bug of installing an incomplete vtable that crashes on the next allocation rather than at the install call.

Parameters
vtableFully-populated vtable (must have all four slots non-NULL).

◆ r_mem_using_system_default()

rboolean r_mem_using_system_default ( void  )

Whether the active vtable still points at libc.

Useful as a sanity guard in code that absolutely must allocate through libc (e.g. interop with foreign code that will free the pointer itself).

Returns
TRUE if the active vtable is the libc default, FALSE if a custom vtable has been installed.

◆ r_memagg()

rsize r_memagg ( rpointer  dst,
rsize  size,
rsize out,
  ... 
)

Aggregate (concatenate) a NULL-terminated list of byte chunks into dst.

Variadic args are pairs of (rconstpointer, rsize) and the list terminates with a NULL pointer. Each chunk that fits within the remaining space in dst is copied and tallied; the first chunk that would overflow ends the aggregation. The total bytes written are returned via *out.

Parameters
dstDestination buffer.
sizeCapacity of dst in bytes.
outReceives the total bytes written (may be NULL).
Returns
Number of chunks copied (which may be less than the number supplied if dst filled up).

◆ r_memaggv()

rsize r_memaggv ( rpointer  dst,
rsize  size,
rsize out,
va_list  args 
)

va_list variant of r_memagg.

Parameters
dstDestination buffer.
sizeCapacity of dst in bytes.
outReceives the total bytes written (may be NULL).
argsPre-started va_list - the caller owns the va_start / va_end book-keeping.
Returns
Number of chunks copied.

◆ r_memclear_secure()

void r_memclear_secure ( rpointer  ptr,
rsize  size 
)

Zero size bytes at ptr in a way the compiler can't elide.

A regular memset before a free is provably unobservable from the caller's perspective and gets removed by the optimiser ("dead store elimination") - which is exactly the wrong outcome for wiping secret material. Use this for buffers that contained keys, scalars, nonces, plaintexts, etc. before they're released.

Stays extern so the platform-specific guarantees (SecureZeroMemory on Win32, explicit_bzero on glibc / *BSD / musl, volatile-loop fallback elsewhere) live in one place and the optimiser can't see through them.

Parameters
ptrDestination buffer (may be NULL or size 0; both are silent no-ops).
sizeNumber of bytes to wipe.

◆ r_memcmp_ct()

int r_memcmp_ct ( rconstpointer  a,
rconstpointer  b,
rsize  size 
)

Constant-time variant of r_memcmp.

Returns 0 iff every byte matches, non-zero otherwise. No early-out on the first mismatch, so wall-clock latency depends only on size and not on which bytes (if any) differ - suitable for comparing MAC tags, signature digests, and similar secret-derived material against attacker-supplied values.

Does not preserve memcmp's sign semantics; only the zero / non-zero distinction is meaningful. Stays extern so the volatile- pointer loop in the implementation isn't sniffed apart by the optimiser.

The non-constant-time r_memcmp / r_memset / r_memcpy / r_memmove inline primitives live in rlib/types/rmemops.h (transitively pulled in through this header) - that placement is forced by their use inside the rendianness.h load / store helpers, which are processed earlier in the include chain.

Parameters
aFirst buffer (may be NULL).
bSecond buffer (may be NULL).
sizeNumber of bytes to compare.
Returns
0 if a and b are byte-equal across size bytes, non-zero otherwise.

◆ r_memdup()

rpointer r_memdup ( rconstpointer  src,
rsize  size 
)

Heap-allocate a copy of size bytes at src.

Behaves like malloc + memcpy. A NULL src or zero size returns NULL (no allocation).

Parameters
srcSource bytes (may be NULL).
sizeNumber of bytes to duplicate.
Returns
Newly-allocated copy, or NULL on NULL src, zero size, or out-of-memory.

◆ r_memdup_agg()

rpointer r_memdup_agg ( rsize out,
  ... 
)

Aggregate a NULL-terminated list of byte chunks into a freshly-allocated buffer.

The allocation is sized to exactly fit the supplied chunks (sum of all sizes in the variadic list). The total bytes written are returned via *out. Returns NULL on out-of-memory or if the list is empty.

Parameters
outReceives the total allocation size (may be NULL).
Returns
Newly-allocated, fully-populated buffer, or NULL.

◆ r_memdup_aggv()

rpointer r_memdup_aggv ( rsize out,
va_list  args 
)

va_list variant of r_memdup_agg.

Parameters
outReceives the total allocation size (may be NULL).
argsPre-started va_list.
Returns
Newly-allocated, fully-populated buffer, or NULL.

◆ r_realloc()

rpointer rpointer r_realloc ( rpointer  ptr,
rsize  size 
)

Resize an existing allocation to size bytes.

Mirrors libc realloc semantics, including the "@p ptr is @c NULL → fresh allocation" and "@p size is zero → may free" corners. The returned pointer is annotated R_ATTR_WARN_UNUSED_RESULT because forgetting to capture it leaks the prior allocation if realloc moved the block.

Parameters
ptrExisting allocation (or NULL).
sizeNew size in bytes.
Returns
New allocation pointer (which may equal ptr), or NULL on failure (in which case ptr is untouched).