  Context: In C, low-level errors, such as buffer overflow and use-after-free,
are a major problem, as they cause security vulnerabilities and hard-to-find
bugs. C lacks automatic checks, and programmers cannot apply defensive
programming techniques because objects (e.g., arrays or structs) lack run-time
information about bounds, lifetime, and types. Inquiry: Current approaches to
tackling low-level errors include dynamic tools, such as bounds or type
checkers, that check for certain actions during program execution. If they
detect an error, they typically abort execution. Although they track run-time
information as part of their runtimes, they do not expose this information to
programmers. Approach: We devised an introspection interface that allows C
programmers to access run-time information and to query object bounds, object
lifetimes, object types, and information about variadic arguments. This enables
library writers to check for invalid input or program states and thus, for
example, to implement custom error handling that maintains system availability
and does not terminate on benign errors. As we assume that introspection is
used together with a dynamic tool that implements automatic checks, errors that
are not handled in the application logic continue to cause the dynamic tool to
abort execution. Knowledge: Using the introspection interface, we implemented a
more robust, source-compatible version of the C standard library that validates
parameters to its functions. The library functions react to otherwise undefined
behavior; for example, they can detect lurking flaws, handle unterminated
strings, check format string arguments, and set errno when they detect benign
usage errors. Grounding: Existing dynamic tools maintain run-time information
that can be used to implement the introspection interface, and we demonstrate
its implementation in Safe Sulong, an interpreter and dynamic bug-finding tool
for C that runs on a Java Virtual Machine and can thus easily expose relevant
run-time information. Importance: Using introspection in user code is a novel
approach to tackling the long-standing problem of low-level errors in C. As new
approaches are lowering the performance overhead of run-time information
maintenance, the usage of dynamic runtimes for C could become more common,
which could ultimately facilitate a more widespread implementation of such an
introspection interface.
