Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

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
bgColor#FFCCCC
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
bgColor#ccccff
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"

...