Errors can occur when incorrect assumptions are made about the type of data being read. These assumptions may be violated, for example, when binary data has been read from a file instead of text from a user's terminal or the output of a process is piped to
stdin. (See FIO14-C. Understand the difference between text mode and binary mode with file streams.) On some systems, it may also be possible to input a null byte (as well as other binary codes) from the keyboard.
Subclause 188.8.131.52 of the C Standard [ISO/IEC 9899:2011] says,
sif successful. If end-of-file is encountered and no characters have been read into the array, the contents of the array remain unchanged and a null pointer is returned.
The wide-character function
fgetws() has the same behavior. Therefore, if
fgetws() returns a non-null pointer, it is safe to assume that the array contains data. However, it is erroneous to assume that the array contains a nonempty string because the data may contain null characters.
Noncompliant Code Example
This noncompliant code example attempts to remove the trailing newline (
\n) from an input line. The
fgets() function is typically used to read a newline-terminated line of input from a stream. It takes a size parameter for the destination buffer and copies, at most,
size - 1 characters from a stream to a character array.
strlen() function computes the length of a string by determining the number of characters that precede the terminating null character. A problem occurs if the first character read from the input by
fgets() happens to be a null character. This may occur, for example, if a binary data file is read by the
fgets() call [Lai 2006]. If the first character in
buf is a null character,
strlen(buf) returns 0, the expression
strlen(buf) - 1 wraps around to a large positive value, and a write-outside-array-bounds error occurs.
This compliant solution uses
strchr() to replace the newline character in the string if it exists:
Incorrectly assuming that character data has been read can result in an out-of-bounds memory write or other flawed logic.
|Supported: Astrée reports defects due to returned (empty) strings.|
|Axivion Bauhaus Suite|
|(general)||Considers the possibility that |
Could detect some violations of this rule (In particular, it could detect the noncompliant code example by searching for
C4911, C4912, C4913
C++4911, C++4912, C++4913
|LDRA tool suite|
|44 S||Enhanced enforcement|
|Avoid accessing arrays out of bounds|
|Polyspace Bug Finder|
|CERT C: Rule FIO37-C||Checks for use of indeterminate string (rule fully covered)|
Key here (explains table format and definitions)
|CERT C Secure Coding Standard||FIO14-C. Understand the difference between text mode and binary mode with file streams||Prior to 2018-01-12: CERT: Unspecified Relationship|
|CERT C Secure Coding Standard||FIO20-C. Avoid unintentional truncation when using fgets() or fgetws()||Prior to 2018-01-12: CERT: Unspecified Relationship|
|CWE 2.11||CWE-241, Improper Handling of Unexpected Data Type||2017-07-05: CERT: Rule subset of CWE|
CERT-CWE Mapping Notes
Key here for mapping notes
CWE-241 and FIO37-C
CWE-241 = Union( FIO37-C, list) where list =
- Improper handling of unexpected data type that does not come from the fgets() function.
Subclause 184.108.40.206, "The
|[Seacord 2013]||Chapter 2, "Strings"|