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.
Noncompliant Code Example
This noncompliant code example attempts to remove the trailing newline new-line (\n) from an input line. The fgets() function is typically used to read a newlinenew-line 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.
| Code Block | ||
|---|---|---|
| ||
char buf[BUFSIZ + 1];
if (fgets(buf, sizeof(buf), stdin) == NULL) {
/* handleHandle error */
}
buf[strlen(buf) - 1] = '\0';
|
| Wiki Markup |
|---|
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()}} is a null character. This may occur, for example, if a binary data file is read by the {{fgets()}} call \[[Lai 06|AA. C References#Lai 06]\]. If the first character in {{buf}} is a null character, {{strlen(buf)}} returns 0 and a write-outside-array-bounds error occurs. |
Compliant Solution
This compliant solution uses strchr() to replace the newline new-line character in the string, if it exists (see FIO36-C. Do not assume a new-line character is read when using fgets()).
| Code Block | ||
|---|---|---|
| ||
char buf[BUFSIZ + 1];
char *p;
if (fgets(buf, sizeof(buf), stdin)) {
p = strchr(buf, '\n');
if (p) {
*p = '\0';
}
}
else {
/* handleHandle error condition */
}
|
Risk Assessment
Assuming character data has been read can result in out-of-bounds memory writes.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
FIO37-C | high | probable | medium | P12 | L1 |
Automated Detection
Fortify SCA Version 5.0 can detect violations of this rule.
Compass/ROSE could detect some violations of this rule. In particular, it could detect the NCCE by searching for fgets(), followed by "strlen() - 1", which could be -1. The crux of this rule is that a string returned by fgets() could still be empty, because the first char is '\0'. There are probably other code examples that violate this guideline; we would need to enumerate them before ROSE could detect them.
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
| Wiki Markup |
|---|
\[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] Section 7.19.7.2, "The {{fgets}} function"
\[[Lai 06|AA. C References#Lai 06]\]
\[[MITRE 07|AA. C References#MITRE 07]\] [CWE ID 119|http://cwe.mitre.org/data/definitions/119.html], "Failure to Constrain Operations within the Bounds of an Allocated Memory Buffer," [CWE ID 241|http://cwe.mitre.org/data/definitions/241.html], and "Failure to Handle Wrong Data Type"
\[[Seacord 05a|AA. C References#Seacord 05]\] Chapter 2, "Strings" |
...