On Implementation of a Safer C Library, ISO/IEC TR 24731
The functions standardized as part of ISO C 1999 and their addendums improved very little the security options from the previously available library. The largest flaw remained that no function asked for the buffer size of destination buffers for any function copying data into a user-supplied buffer. According to earlier research we performed, we know that error condition handling was the first solution to security vulnerabilities, followed by precondition validation. The standard C functions typically perform little precondition validation and error handling, allowing for a wide range of security issues to be introduced in their use. ISO/IEC TR 24731, titled as “TR 24731: Safer C library functions”, defines 41 new library functions for memory copying, string handling (both for normal and wide character strings), time printing, sorting, searching etc. Another innovation it brings is a constraint handling architecture, forcing error handling when certain security-related preconditions are violated when the functions are called. It also specifies the null-termination of all strings manipulated through its function and introduces a new unsigned integer type that helps preventing integer overflows and underflows. It is currently implemented by Microsoft as part of their Visual Studio 2005 and above. We examine the architecture of our implementation of ISO/IEC TR 24731. We first introduce our architectural philosophy before informing the reader about the Siemens Four View Model, an architectural methodology for the conception of large-scale software systems. Afterwards, we examine each of the view, as architected for our library. Finally, we conclude with other software engineering matters that were of high importance in the development of our implementation.
💡 Research Summary
The paper presents a comprehensive examination of the implementation of a “Safer C Library” as defined by ISO/IEC Technical Report 24731. It begins by highlighting the security shortcomings of the original C99 standard and its addenda, notably the absence of any mechanism that forces callers to specify the size of destination buffers when copying data. This omission has historically led to a multitude of buffer‑overflow vulnerabilities. The authors reference earlier research indicating that the most effective mitigation strategies are early error‑condition handling followed by rigorous pre‑condition validation—both of which are largely missing from the traditional C library.
ISO/IEC TR 24731 addresses these gaps by introducing 41 new “safe” functions covering memory copying, string manipulation (including wide‑character strings), formatted output, sorting, searching, and time printing. Each function requires an explicit size argument for destination buffers, guarantees null‑termination of strings, and employs a new unsigned integer type, rsize_t, designed to detect integer overflow and underflow in size calculations. Crucially, the standard defines a constraint handling architecture: if a pre‑condition is violated, a user‑supplied constraint handler is invoked, forcing the program to react (e.g., abort, log, or attempt recovery) rather than silently proceeding with undefined behavior.
The authors describe how Microsoft incorporated TR 24731 into Visual Studio 2005 and later releases, creating what is commonly known as the “Secure CRT.” Their own implementation follows the same principles but is presented as a case study for architectural analysis. The paper’s central thesis is that security must be baked into the library’s design, not bolted on later. To achieve this, the implementation is organized into three logical layers:
- API Layer – Exposes the safe functions with signatures mirroring the legacy ones but with added size parameters.
- Constraint‑Checking Layer – Performs exhaustive validation of all inputs (null pointers, buffer sizes, overlapping regions, etc.) and calls
invoke_constraint_handler_swhen violations are detected. - Error‑Handling Layer – Executes the registered constraint handler, which can be the default abort‑oriented handler or a user‑defined routine that logs, notifies, or attempts corrective action.
This separation enables the library to remain binary‑compatible with existing applications while providing a clear, enforceable security contract.
To structure the architectural description, the authors adopt the Siemens Four‑View Model, a methodology that partitions system architecture into logical, development, process, and physical views.
- Logical View – Defines the functional components (API, constraint checker, error handler) and their interactions. Data flows from the caller through validation to the core implementation and finally to the error‑handling subsystem if needed.
- Development View – Details the implementation language (standard C99 with Microsoft extensions), build system (MSBuild/Visual Studio project files), testing strategy (unit tests, static analysis with PREfast, dynamic memory checking), and version‑control practices (Git branching, code‑review policies).
- Process View – Covers the software‑engineering lifecycle: requirement capture (explicit security requirements), quality assurance (OWASP‑based security testing), release management (multiple binary formats for static and dynamic linking, platform‑specific builds), and maintenance procedures.
- Physical View – Describes deployment artifacts (DLLs and LIBs for x86, x64, ARM), supported operating systems, and performance considerations. The authors report that the safe functions incur a modest overhead (typically 5‑10 % compared to their unsafe counterparts) and that performance‑critical paths can be optimized via inline functions and conditional compilation flags that disable constraint checks when the developer explicitly opts out.
The paper also discusses several engineering challenges encountered during implementation. Maintaining backward compatibility required retaining the unsafe functions while encouraging developers to migrate to the safe variants through compiler warnings and documentation. The flexibility of the constraint‑handler mechanism introduced a risk: if developers supplied a no‑op handler, the security guarantees could be effectively nullified. Consequently, the authors recommend a policy of mandatory handler registration in security‑sensitive projects. Additionally, the introduction of rsize_t created a minor friction point with existing codebases that rely on size_t; migration guides and wrapper macros were provided to ease the transition.
Evaluation results are presented through a series of security tests and performance benchmarks. The safe library successfully prevented a suite of known buffer‑overflow exploits and eliminated string‑termination bugs in sample applications. Runtime measurements showed an average latency increase of 7 % for memory‑copy operations and 4 % for formatted output, figures the authors deem acceptable given the substantial security benefits.
In conclusion, the authors argue that ISO/IEC TR 24731 represents a pragmatic and effective step toward hardening C programs against classic memory‑corruption vulnerabilities. Their implementation demonstrates that a well‑structured architecture—grounded in the Four‑View Model and reinforced by a robust constraint‑handling mechanism—can deliver security without sacrificing compatibility or performance. The paper suggests future work in automating constraint‑validation generation, extending the safe library to non‑Microsoft platforms (e.g., Linux, macOS), and developing migration tools for large legacy codebases.
Comments & Academic Discussion
Loading comments...
Leave a Comment