Avoid in-band error indicators while designing interfaces. This practice is commonly used by C library functions but is not recommended. One example from the C Standard of a troublesome in-band error indicator is EOF
. (See see FIO34-C. Use int to capture the return value of character IO functions and FIO35-C. Use feof() and ferror() to detect end-of-file and file errors when sizeof(int) == sizeof(char).) Distinguish between characters read from a file and EOF or WEOF). Another problematic use of in-band error indicators from the C Standard involving the size_t
and time_t
types is described by MSC31by
...
- integer conversions do not result in lost or misinterpreted data
- FLP07-C. Cast the return value of a function that returns a floating-point type
- INT18-C. Evaluate integer expressions in a larger size before comparing or assigning to that size
...
Noncompliant Code Example (sprintf()
)
This noncompliant code example is from the Linux Kernel Mailing List archive site, although similar examples are common.:
Code Block | ||||
---|---|---|---|---|
| ||||
int i; ssize_t count = 0; for (i = 0; i < 9; ++i) { count += sprintf( buf + count, "%02x ", ((u8 *)&slreg_num)[i] ); } count += sprintf(buf + count, "\n"); |
...
This compliant solution shows the redesigned API for sprintf()
from the CERT managed string library [Burch 2006].:
Code Block | ||||
---|---|---|---|---|
| ||||
errno_t sprintf_m( string_m buf, const string_m fmt, int *count, ... ); |
...
where rbytes
is a pointer to a size_t
. If no error occurs, and rbytes
is not NULL
, its value is set to the total number of bytes read, and read()
returns 0. If an error occurs, read()
returns a nonzero value indicating the error.
Noncompliant Code Example (
...
C11, Annex K)
In this noncompliant code example, the error handler returns normally, but the strcpy_s()
function's return value is not checked.:
Code Block | ||||
---|---|---|---|---|
| ||||
constraint_handler_t handle_errors(void) { constraint_handler_t data; /* Define what to do when error occurs */ return data; } /* ... */ set_constraint_handler(handle_errors); /* ... */ /* Returns zero on success */ errno_t function(char *dst1, size_t dst_size) { char src1[100] = "hello"; strcpy_s(dst1, sizeof(dst1)dst_size, src1); /* * At this point strcpy_s may have yielded an * error, and handle_errors() might have returned. */ /* ... */ return 0; } |
Compliant Solution (
...
C11, Annex K)
In this compliant solution, the error handler terminates the program, ensuring that strcpy_s()
never returns unless it fully succeeds.:
Code Block | ||||
---|---|---|---|---|
| ||||
/* * The abort_handler_s() function writes * a message on the * standard error stream and * then calls the abort() function. */ set_constraint_handler(abort_handler_s); /* ... */ /* Returns zero on success */ errno_t function(char *dst1, size_t dst_size) { char src1[100] = "hello"; strcpy_s(dst1, sizeof(dst1)dst_size, src1); /* * Because abort_handler_s() never returns, * we only get here only if strcpy_s() succeeds. */ /* ... */ return 0; } |
Exceptions
ERR02-EX1: Null pointers are another example of an in-band error indicator. Use of null pointers is allowed because it is supported by the language. According to the C Standard, Section subclause 6.3.2.3 [ISO/IEC 9899:2011]:
If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
ERR02-EX2: You may use a function returning in-band error indicators if you can securely guarantee the program will not try to continue processing should an error occur in the function. For example, the functions defined in TR24731-1 C11 Annex K provide hooks for internal constraint violations. If a constraint violation handler is guaranteed not to return upon an error, then you may safely ignore errors returned by these functions. You might accomplish this by having the constraint-violation handler call abort()
or longjmp()
, for instance.
See ERR03-C. Use runtime-constraint handlers when calling the bounds-checking interfaces for more on the functions defined in TR24731-1C11 Annex K.
Risk Assessment
The risk in using in-band error indicators is difficult to quantify and is consequently given as low. However, if the use of in-band error indicators results in programmers' failing to check status codes or incorrectly checking them, the consequences can be more severe.
Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
ERR02-C |
Low |
Unlikely |
High | P1 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Parasoft C/C++test |
| CERT_C-ERR02-a | The input/output functions from the 'cstdio' and 'cwchar' libraries should not be used |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
SEI CERT C++ |
Coding Standard | VOID ERR02-CPP. Avoid in-band error indicators |
Bibliography
[Burch 2006] |
[ISO/IEC 9899:2011] |
Subclause 6.3.2, "Other Operands" |
...