# memory error detection and prevention part of [c memory management](../memory.html) # detection (development and testing only) * these mechanisms are not shipped to endusers * any runtime or workflow cost is paid only during development and testing * sections are ordered by increasing invasiveness and disruption of a normal build and execution flow ## runtime-supervised execution * operates on existing binaries * does not require recompilation or special build flags * execution takes place under a supervising environment that observes and instruments behavior ### valgrind * runs the program inside a virtualized execution engine * instruments every instruction at runtime * detects: * heap buffer overflows and underflows * use-after-free * invalid free * memory leaks * uses of uninitialized memory * properties: * no compiler support required * works with third-party and legacy binaries * very high runtime overhead * execution semantics differ substantially from native execution * diagnostic model: * reports memory errors when they are observed * attribution may be less precise than compiler-instrumented tools * effective when rebuilds are not possible or undesirable ## compile-time diagnostics * requires recompilation * produces ordinary binaries with no runtime instrumentation * does not change execution behavior ### compiler warnings * enabled via diagnostic flags * conservative and syntactic in nature * what they catch: * uninitialized variables * suspicious pointer arithmetic * implicit truncation or signedness changes affecting sizes * mismatched types in memory and string operations * properties: * zero runtime cost * low false-negative tolerance * false positives accepted as a tradeoff ### static analysis * path-sensitive analysis performed at compile time or as a separate build step * what it targets: * null dereference paths * double free patterns * leaks along error paths * inconsistent ownership conventions * properties: * no runtime cost * incomplete by design * results depend heavily on code structure and annotations ## runtime-instrumented builds * requires recompilation with special instrumentation enabled * modifies memory layout and execution semantics * highest diagnostic precision and highest disruption ### addresssanitizer * compiler-inserted runtime checks for memory safety * detects: * heap buffer overflow and underflow * stack buffer overflow * use-after-free * use-after-scope * double free and invalid free * execution model: * guard regions around objects * quarantining of freed memory * shadow memory checks on every access * diagnostic properties: * aborts at the first invalid access * explicit classification of the violated rule * stack traces typically include allocation and free sites ### undefined behavior sanitizer * runtime checks for semantic undefined behavior * detects: * misaligned memory access * invalid pointer arithmetic * signed integer overflow * invalid shifts * role in memory error detection: * many memory corruptions originate from earlier semantic violations * detects these before they propagate into allocator state ### leak sanitizer * detects memory that remains allocated at program termination * properties: * focuses on lifetime and ownership violations * does not detect corruption * typically used in conjunction with other sanitizers ### memory sanitizer * tracks propagation of uninitialized memory * detects: * reads of uninitialized data * use of uninitialized values in control flow and memory access * properties: * very high overhead * requires all code, including libraries, to be instrumented * effective for subtle initialization bugs that evade other tools * ordering rationale: * start with supervision when rebuilds are undesirable * escalate to static diagnostics for low-cost signal * use runtime instrumentation to localize hard memory errors precisely # prevention and hardening (ships to endusers) * these mechanisms are enabled in release builds * their cost is paid by all endusers at runtime * they are ordered by increasing behavioral impact on the shipped program * their purpose is mitigation and containment, not precise diagnosis ## stack protection * inserts integrity checks into selected stack frames * protects return addresses and adjacent control data * mechanism: * a guard value is placed between local objects and control data * the guard is verified on function exit * effect: * detects some stack buffer overflows * converts silent control-flow corruption into immediate termination * limitations: * does not protect all stack objects * does not address heap corruption * does not localize the original overflow ## fortified libc interfaces * replaces some standard library calls with checked variants * depends on compile-time knowledge of object sizes * mechanism: * when destination size is known, copy and formatting functions validate lengths * violations cause immediate abort * effect: * prevents some classes of buffer overflow from silently corrupting memory * especially effective for string and memory copy misuse * limitations: * only applies to a subset of libc functions * ineffective when object size cannot be proven * failure occurs at the call site, not necessarily at the original logic error ## allocator hardening and consistency checks * allocator-internal integrity validation * enabled by default or via build-time configuration, depending on platform * mechanism: * metadata consistency checks * freelist integrity validation * abort-on-detection of invariant violations * effect: * converts latent heap corruption into deterministic termination * raises the cost of exploitation * limitations: * detection is downstream of the original bug * error messages describe allocator invariants, not program logic * not a substitute for memory error detection during development ## role and interpretation * these mechanisms: * reduce exploitability * bound damage * improve failure determinism * they do not: * explain why the memory error occurred * identify the originating instruction reliably * replace development-time detection tools * mental model: * prevention and hardening are safety nets * detection is required to find and fix defects * both are necessary, but they serve different phases of the lifecycle