|
rlib
Convenience library for useful things
|
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. | |
Heap / stack allocators, byte-buffer operations, and pattern-based memory scanning.
| #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.
| size | Number of bytes (typically a small constant - large requests risk stack overflow). |
| enum RMemScanResultType |
Status codes returned by r_mem_scan_pattern.
| enum 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) 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.
| count | Number of elements. |
| size | Size of each element in bytes. |
NULL on failure. | 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).
| ptr | Allocation to release. |
Allocate size uninitialised bytes on the heap.
Routes through the currently-installed RMemVTable.
| size | Number of bytes (zero is implementation-defined). |
NULL on failure. Allocate size zero-initialised bytes on the heap.
Implemented as calloc(1, size) through the active vtable.
| size | Number of bytes. |
NULL on failure. | 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.
| out | Destination vtable (must be non-NULL). |
| 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.
| mem | Memory region (may be NULL). |
| size | Region length in bytes. |
| byte | Byte to search for. |
NULL if not found (or mem is NULL). | 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.
| mem | Memory region (may be NULL). |
| size | Region length in bytes. |
| byte | Set of bytes to match (may be NULL). |
| bytes | Number of bytes in byte. |
NULL. | 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.
| mem | Haystack (may be NULL). |
| size | Haystack length in bytes. |
| data | Needle bytes (may be NULL). |
| datasize | Needle length in bytes. |
mem, or NULL. | 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.
| mem | Haystack (must be non-NULL). |
| size | Haystack length in bytes. |
| pattern | NUL-terminated pattern string (must be non-NULL). |
| result | Receives the freshly-allocated result struct (must be non-NULL). Set to NULL if no allocation was attempted. |
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. | 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.
| mem | Haystack. |
| size | Haystack length in bytes. |
| pattern | NUL-terminated pattern string. |
| end | If non-NULL, receives one past the last byte of the match. |
NULL on no match / parse error / OOM. | 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.
| vtable | Fully-populated vtable (must have all four slots non-NULL). |
| 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).
TRUE if the active vtable is the libc default, FALSE if a custom vtable has been installed. 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.
| dst | Destination buffer. |
| size | Capacity of dst in bytes. |
| out | Receives the total bytes written (may be NULL). |
dst filled up). va_list variant of r_memagg.
| dst | Destination buffer. |
| size | Capacity of dst in bytes. |
| out | Receives the total bytes written (may be NULL). |
| args | Pre-started va_list - the caller owns the va_start / va_end book-keeping. |
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.
| ptr | Destination buffer (may be NULL or size 0; both are silent no-ops). |
| size | Number of bytes to wipe. |
| 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.
| a | First buffer (may be NULL). |
| b | Second buffer (may be NULL). |
| size | Number of bytes to compare. |
a and b are byte-equal across size bytes, non-zero otherwise. | 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).
| src | Source bytes (may be NULL). |
| size | Number of bytes to duplicate. |
NULL on NULL src, zero size, or out-of-memory. 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.
| out | Receives the total allocation size (may be NULL). |
NULL. va_list variant of r_memdup_agg.
| out | Receives the total allocation size (may be NULL). |
| args | Pre-started va_list. |
NULL. 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.
| ptr | Existing allocation (or NULL). |
| size | New size in bytes. |
ptr), or NULL on failure (in which case ptr is untouched).