Editor's Note: Since this article first appeared, Bo Berry has released the Safe Math Library which complements the Safe C Library by catching arithmetic overflows.

The recently released Safe C Library implements a subset of the functions defined in the ISO TR24731 specification which is designed to provide alternative functions for the C Library (as defined in ISO/IEC 9899:1999) that promotes safer, more secure programming in C.

The Safe C Library (available for download here) provides bound checking memory and string functions per ISO/IEC TR24731. These functions are alternative functions to the existing Standard C Library. The functions verify that output buffers are large enough for the intended result, and return a failure indicator if they are not. Optionally, failing functions call a "runtime-constraint handler" to report the error. Data is never written past the end of an array. All string results are null terminated. In addition, the functions in ISO/IEC TR 24731-1:2007 are re-entrant: they never return pointers to static objects owned by the function.

Included in the Safe C Library are extensions to the specification to provide a complementary set of functions with like behavior. The library can be used to mitigate (that is, lessen) software security problems. When used properly, these functions decrease the danger of buffer overruns and the vulnerability of cyber attacks.

The ISO TR24731 Bounds Checking Interface documents indicate that the key motivation for the new specification is to help mitigate the ever increasing security attacks -- specifically the buffer overrun. According to the rationale document:

Buffer overrun attacks continue to be a security problem. Roughly 10% of vulnerability reports cataloged by CERT from 01/01/2005 to 07/01/2005 involved buffer overflows. Preventing buffer overruns is the primary, but not the only, motivation for this technical report.

The rationale document goes on to say that:

...these only mitigate, that is lessen, security problems. When used properly, these functions decrease the danger buffer overrun attacks. Source code may remain vulnerable due to other bugs and security issues. The highest level of security is achieved by building in layers of security utilizing multiple strategies.

The rationale document also lists the following key points for TR24731:

Guard against overflowing a buffer

Do not produce unterminated strings

Do not unexpectedly truncate strings

Provide a library useful to existing code

Preserve the null terminated string datatype

Only require local edits to programs

Library based solution

Support compile-time checking

Make failures obvious

Zero buffers, null strings

Runtime-constraint handler mechanism

Support re-entrant code

Consistent naming scheme

Have a uniform pattern for the function parameters and return type

Deference to existing technology

The Safe C Library only implements a subset of the functions defined in the specification. Included in the library are extensions to the specification to provide a complementary set of functions with like behavior.

Among the design considerations for Safe C are:

Use of errno . The TR24731 specification says an implementation may set errno for the functions defkned in the technical report, but is not required to. This library does not set errno. The library does use errno return codes as required by functional APIs. Specific Safe C String and Safe C Memory errno codes are defined in the safe_errno.h file.

. The TR24731 specification says an implementation may set for the functions defkned in the technical report, but is not required to. This library does not set errno. The library does use return codes as required by functional APIs. Specific Safe C String and Safe C Memory codes are defined in the safe_errno.h file. Runtime-constraints . Per the spec, the library verifies that the calling program does not violate the function's runtime-constraints. If a runtime-constraint is violated, the library calls the currently registered runtime-constraint handler. Per the spec, multiple runtime-constraint violations in the same call to a library function result in only one call to the runtime-constraint handler. The first violation encountered invokes the runtime-constraint handler. The runtime-constraint handler might not return. If the handler does return, the library function whose runtime-constraint was violated returns an indication of failure as given by the function's return.

. Per the spec, the library verifies that the calling program does not violate the function's runtime-constraints. If a runtime-constraint is violated, the library calls the currently registered runtime-constraint handler. Per the spec, multiple runtime-constraint violations in the same call to a library function result in only one call to the runtime-constraint handler. The first violation encountered invokes the runtime-constraint handler. The runtime-constraint handler might not return. If the handler does return, the library function whose runtime-constraint was violated returns an indication of failure as given by the function's return. rsize_t . The specification defines a new type. This type, rsize_t , is conditionally defined in the safe_lib.h header file.

. The specification defines a new type. This type, , is conditionally defined in the safe_lib.h header file. RSIZE_MAX Macro . The specification defines the macro RSIZE_MAX which expands to a value of type rsize_t . The specification uses RSIZE_MAX for both the string functions and the memory functions. This implementation defines two macros: RSIZE_MAX_STR and RSIZE_MAX_MEM. RSIZE_MAX_STR defines the range limit for the safe string functions. RSIZE_MAX_MEM defines the range limit for the safe memory functions. The point is that string limits can and should be different from memory limits.

. The specification defines the macro RSIZE_MAX which expands to a value of type . The specification uses RSIZE_MAX for both the string functions and the memory functions. This implementation defines two macros: RSIZE_MAX_STR and RSIZE_MAX_MEM. RSIZE_MAX_STR defines the range limit for the safe string functions. RSIZE_MAX_MEM defines the range limit for the safe memory functions. The point is that string limits can and should be different from memory limits. Configurations . Optional features and system dependent features can be configured by macros in the Safe C library header files. These can be found by a grep of the files: grep CONFIGURE *.h.

. Optional features and system dependent features can be configured by macros in the Safe C library header files. These can be found by a grep of the files: grep CONFIGURE *.h. Header Files. The specification states the variopus functions would be added to existing Standard C header files: stdio.h, string.h, etc. This implementation separates the memory related functions into the safe_mem_lib.h header and the string related functions into the safe_str_lib.h header. The make file builds a single library safe_lib.a in the ../lib directory. It is possible to split the make such that a separate safe_mem_lib.a and safe_str_lib.a are built. It is also possible to integrate the prototypes into the Standard C header files, but that may require changes to your development tool chain.

Acknowledgements

Thanks to Safe C Project Adminstrator Bo Berry who prepared the readme file on which this short description is based.