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
Incorrectly 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.
Related Guidelines
CERT C++ Secure Coding Standard | FIO36-CPP. Do not assume a new-line character is read when using fgets() |
Bibliography
[Lai 2006] | |
[Seacord 2013] | Chapter 2, "Strings" |