The fgets()
function is typically used to read a newline-terminated line of input from a stream. The fgets()
function takes a size parameter for the destination buffer and copies, at most, size-1
characters from a stream to a string. Truncation errors can occur if the programmer assumes that the last character in the destination string is a newline.
The fgetws()
function is similarly affected.
Noncompliant Code Example
This noncompliant code example attempts to remove the trailing newline (\n
) from an input line.
char buf[BUFSIZ + 1]; if (fgets(buf, sizeof(buf), stdin)) { if (*buf) { /* see FIO37-C */ buf[strlen(buf) - 1] = '\0'; } } else { /* Handle error condition */ }
However, if the last character in buf
is not a newline, this code overwrites an otherwise-valid character.
Compliant Solution
This compliant solution uses strchr()
to replace the newline character in the string (if it exists). The equivalent solution for fgetws()
would use wcschr()
.
char buf[BUFSIZ + 1]; char *p; if (fgets(buf, sizeof(buf), stdin)) { p = strchr(buf, '\n'); if (p) { *p = '\0'; } } else { /* handle error condition */ }
An obvious alternative is to leave room in the buffer for one more character, and when no newline is transferred, append a newline followed by a null-termination character. This approach is unsafe, because it quietly accepts an input that is not what was actually intended, with unknown consequences.
Risk Assessment
Assuming a newline character is read by fgets()
or fgetws()
can result in data truncation.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
FIO36-C |
medium |
likely |
medium |
P12 |
L1 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[Lai 06]]
[[Seacord 05a]] Chapter 2, "Strings"
[[ISO/IEC 9899:1999]] Section 7.19.7.2, "The fgets
function"
FIO35-C. Use feof() and ferror() to detect end-of-file and file errors when sizeof(int) == sizeof(char) 09. Input Output (FIO) FIO37-C. Don't assume character data has been read