|
Safe API Framework
Layered API framework for safety-related applications (ERTMS RBC reference targeting CENELEC EN 50128 SIL 4)
|
Status: Accepted Date: 2026-08-20 Applies to: new include/safeapi/memory/sapi_mem_util.h (header-only, no src/, no SAFEAPI_ENABLE_* option, no tests/ executable of its own - see §2.2/§4).
safeAPIRBC2oo2 (downstream, separate repo) calls libc memset()/ memcpy()/memcmp() directly across ~25 of its own application files (~90 call sites) - fixed-size struct zeroing, buffer copies for the wire codecs, byte-for-byte session comparisons. This framework itself does the same in its own src//posix_backend files. Direct <string.h> calls are not a MISRA rule violation on their own, but this project's own posture (this repo's CLAUDE.md: "no dynamic memory... prefer a checked conversion helper over a bare C-style cast") already favors a single, reviewed, intention-revealing wrapper over scattered direct libc calls for other primitives (sapi_buffer_t's own bounds-checked read/write helpers instead of raw pointer arithmetic being the closest existing precedent) - a downstream integrator asked for the same treatment here: route every fixed-size fill/copy/compare through one small framework header instead of <string.h> directly, so an audit for "does this codebase call libc memory functions directly" has exactly one file to check.
No such wrapper exists in this framework today - sapi_memory.h is a fixed-block POOL ALLOCATOR (sapi_mem_pool_create()/_acquire()/ _release()), a completely different concern (managing a bounded set of reusable blocks, not filling/copying/comparing bytes within one already- owned buffer) - confirmed by a repository-wide search finding no sapi_mem_set/_copy/_compare-shaped function anywhere.
sapi_mem_set(dest, value, count) / sapi_mem_copy(dest, src, count) / sapi_mem_compare(a, b, count) wrap memset()/memcpy()/memcmp() exactly, with no bounds-checking of their own (callers already own both buffers and their sizes - the same "caller-owned storage, no hidden state" convention this framework's own sapi_buffer_t and every downstream channel_ab_* module already follow) and no variable-length text handling (strcpy/strcat/strlen-style functions are deliberately out of scope - this framework and every application built on it work in fixed-size buffers throughout, CLAUDE.md's "no malloc/free" rule, so there is no genuine need for a variable-length string primitive; adding one now would be speculative scope this ADR's own triggering request never asked for).
Same rationale as ADR-030 §2.3 (sapi_notify.h): these are static inline wrappers with no OS dependency and no runtime state of their own