Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: wordsmithing

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 Standard of a troublesome in-band error indicator is EOF (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 Standard involving the size_t and time_t types is described by MSC31by 

...

Noncompliant Code Example (sprintf())

This noncompliant

...

Non-Compliant Code Example

This specific non-compliant code example is from the Linux Kernel Mailing List archive site at http://lkml.org/ , although similar examples are common.:

Code Block
bgColor#FFCCCC
langc

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");

The sprintf() function returns the number of characters written in the array, not counting the terminating null character. This number is frequently added to an existing counter to keep track of the location of the index into the array. However, the call to sprintf() can (and will) return -1 −1 on error conditions, such as an encoding error. If this error happens on the first call (which is likely), the count variable, already at zero0, is decremented. If this index is subsequently used, it will result in an out-of-bounds read or write.

Compliant Solution

...

(sprintf_m())

This compliant solution shows the redesigned API for {{sprintf()}} from the CERT managed string library \ [[Burch 06|AA. C References#Burch06]\].Burch 2006]:

Code Block
bgColor#ccccff
langc

errno_t sprintf_m(
  string_m buf, 
  const string_m fmt, 
  int *count, 
  ...
);

The sprintf_m() API separates out the return status of the function from information about the number of characters written. In this case, *count is set to the number of characters written in buf while , and the return value indicates the return status. Returning the status as the return value of the function increases the likelihood that a programmer will check the return status of the function.

The preceding code example can be amended as follows:

Code Block
bgColor#ccccff
langc
int i;
rsize_t count = 0;
errno_t err;

for (i = 0; i < 9; ++i) {
  err = sprintf_m(
    buf + count, "%02x ", &count, ((u8 *)&slreg_num)[i]
  );
  if (err != 0) {
    /* Handle print error */
  }
}
err = sprintf_m(
  buf + count, "%02x ", &count, ((u8 *)&slreg_num)[i]
);
if (err != 0) {
  /* Handle print error */
}

Noncompliant Code Example (POSIX ssize_t)

The ssize_t data type is designed as a "signed representation of size_t." Consequently, it is often used as a return type for functions that can return an unsigned value upon success and a negative value upon error. For instance, the POSIX read() function has the following signature:

Code Block
bgColor#FFCCCC
langc
ssize_t read(int fildes, void *buf, size_t nbyte);

read() returns −1 if an error occurs; if no errors occur, it returns the number of bytes actually read.

As with all in-band error indicators, this type is not recommended because developers are tempted to ignore the possibility that a ssize_t value is negative.

Compliant Solution (POSIX size_t)

An alternative hypothetical signature for the read() function is

Code Block
bgColor#CCCCFF
langc
errno_t read(int fildes, void *buf, size_t nbyte, size_t* rbytes);

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.

Exceptions

ERR02-EX1: Null pointers are another example of an in-band error indicator. Use of the null pointers is not quite as bad allowed because it is supported for by the language. According to C99 Section the C Standard, subclause 6.3.2.3 , "Pointers"[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.

Risk Analysis

ERR02-EX2: You may design a function that returns in-band error indicators if it is possible to securely guarantee that the program will not try to continue processing should an error occur in the function. For example, after calling the glibc function feenableexcept(FE_OVERFLOW), you can call the exp function without needing to check for overflow on the result yourself, because if it occurs, then a SIGFPE will cause the program to terminate in a similar manner as abort().

Risk Assessment

The risk in The risk of 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 status codethem, the consequences can be more severe.

Recommendation

Severity

Likelihood

Remediation Cost

Detectable

Repairable

Priority

Level

ERR02-

A

C

Low

low

Unlikely

unlikely

No

high

No

P1

L3

Automated Detection

Tool

Version

Checker

Description

Parasoft C/C++test

Include Page
Parasoft_V
Parasoft_V

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.

References

Wiki Markup
\[[Burch 06|AA. C References#Burch06]\]
\[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\] Section 6.2.4, "Storage durations of objects," and Section 7.20.3, "Memory management functions"
\[[ISO/IEC PDTR 24772|AA. C References#ISO/IEC PDTR 24772]\] "NZN Returning error status"

Related Guidelines

Bibliography

[Burch 2006]
[ISO/IEC 9899:2011]

Subclause 6.3.2, "Other Operands"
Annex K, "Bounds-checking Interfaces"


...

Image Added Image Added Image AddedERR01-A. Use ferror() rather than errno to check for any accumulated error      13. Error Handling (ERR)       ERR30-C. Set errno to zero before calling a function, and use it only after the function returns a value indicating failure