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 buffer size is smaller than the input string.
The fgetws() function is similarly affected.
This noncompliant code example copies the input string into a buffer, and assumes it captured all of the user's input.
#include <stdbool.h>
#include <stdio.h>
bool get_data(char *buffer, int size) {
if (fgets(buffer, size, stdin)) {
return true;
}
return false;
}
void func(void) {
char buf[8];
if (get_data(buf, sizeof(buf))) {
printf("The user input %s\n", buf);
} else {
printf("Error getting data from the user\n");
}
} |
However, if the last character in buf is not a newline and the stream is not at the end-of-file marker, the buffer was too small to contain all of the data from the user. For instance, since the buffer is only 8 characters in length, if the user input "Hello World\n", the buffer would contain "Hello W" and the null terminator.
This compliant solution examines the end-of-file marker for the stream, and the last character in the buffer to determine whether it is a newline or not. If it is the end of file, or the last character is a newline, then the buffer contains all of the user's input. However, if it is not at the end-of-file and not a newline, then the user's input has been cut short.
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
bool get_data(char *buffer, int size) {
if (fgets(buffer, size, stdin)) {
size_t len = strlen(buffer);
return feof(stdin) || buffer[len] == '\n';
}
return false;
}
void func(void) {
char buf[8];
if (get_data(buf, sizeof(buf))) {
printf("The user input %s\n", buf);
} else {
printf("Error getting data from the user\n");
}
} |
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 |
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
| CERT C++ Secure Coding Standard | FIO36-CPP. Do not assume a new-line character is read when using fgets() |
| [Lai 2006] | |
| [Seacord 2013] | Chapter 2, "Strings" |