Errors can occur when 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. (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.
Section Subclause 7.21.7.2 of the C Standard [ISO/IEC 9899:2011] says,
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdio.h> #include <string.h> void func(void) { char buf[BUFSIZ + 1]; if (fgets(buf, sizeof(buf), stdin) == NULL) { /* Handle error */ } buf[strlen(buf) - 1] = '\0'; } |
The 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 and a write-outside-array-bounds error occurs.
...
This compliant solution uses strchr() to replace the newline character in the string if it exists. (See FIO36FIO20-C. Do not assume a newline character is read Avoid unintentional truncation when using fgets() or fgetws().)
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdio.h> #include <string.h> void func(void) { char buf[BUFSIZ + 1]; char *p; if (fgets(buf, sizeof(buf), stdin)) { p = strchr(buf, '\n'); if (p) { *p = '\0'; } } else { /* Handle error condition */ } } |
Risk Assessment
Assuming character data has been read can result in an out-of-bounds memory write.
...
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
| CERT C Secure Coding Standard | FIO14-C. Understand the difference between text mode and binary mode with file streams FIO20-C. Avoid unintentional truncation when using fgets() or fgetws() |
| CERT C++ Secure Coding Standard | FIO37-CPP. Do not assume character data has been read |
| MITRE CWE | CWE-119, Failure to constrain operations within the bounds of an allocated memory buffer CWE-241, Failure to handle wrong data type |
Bibliography
| [ISO/IEC 9899:2011] | Section Subclause 7.21.7.2, "The fgets Function" |
| [Lai 2006] | |
| [Seacord 2013] | Chapter 2, "Strings" |
...