The fgets()
function is typically used to read a new-line 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 new-line, 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 new-line is transferred, append a new-line 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
Incorrectly assuming a new-line 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.
Other Languages
This rule appears in the C++ Secure Coding Standard as FIO36-CPP. Do not assume a new-line character is read when using fgets().
References
[ISO/IEC 9899:1999] Section 7.19.7.2, "The fgets
function"
[Lai 06]
[Seacord 05a] Chapter 2, "Strings"
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. Do not assume that fgets() returns a nonempty string when successful