Reputation: 398
This quote is from the GNU manual
Warning: If the input data has a null character, you can’t tell. So don’t use fgets unless you know the data cannot contain a null. Don’t use it to read files edited by the user because, if the user inserts a null character, you should either handle it properly or print a clear error message. We recommend using getline instead of fgets.
As I usually do, I spent time searching before asking a question, and I did find a similar question on Stack Overflow from five years ago: Why is the fgets function deprecated?
Although GNU recommends getline
over fgets
, I noticed that getline
in stdio.h
takes any size line. It calls realloc
as needed. If I try to set the size to 10 char:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *buffer;
size_t bufsize = 10;
size_t characters;
buffer = (char *)malloc(bufsize * sizeof(char));
if( buffer == NULL)
{
perror("Unable to allocate buffer");
exit(1);
}
printf("Type something: ");
characters = getline(&buffer,&bufsize,stdin);
printf("%zu characters were read.\n",characters);
printf("You typed: '%s'\n",buffer);
return(0);
}
In the code above, type any size string, over 10 char, and getline will read it and give you the right output.
There is no need to even malloc
, as I did in the code above — getline
does it for you. I'm setting the buffer to size 0, and getline
will malloc
and realloc
for me as needed.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *buffer;
size_t bufsize = 0;
size_t characters;
printf("Type something: ");
characters = getline(&buffer,&bufsize,stdin);
printf("%zu characters were read.\n",characters);
printf("You typed: '%s'\n",buffer);
return(0);
}
If you run this code, again you can enter any size string, and it works. Even though I set the buffer size to 0.
I've been looking at safe coding practices from CERT guidelines www.securecoding.cert.org
I was thinking of switching from fgets
to getline
, but the issue I am having, is I cannot figure out how to limit the input in getline
. I think a malicious attacker can use a loop to send an unlimited amount of data, and use up all the ram available in the heap?
Is there a way of limiting the input size that getline
uses or does getline
have some limit within the function?
Upvotes: 2
Views: 2158
Reputation: 215259
The GNU manual is just bad. Limiting the input length is usually the right thing to do, especially if input is untrusted, and fgets
does this correctly. getline
cannot be used safely in such a context.
Upvotes: 1
Reputation: 827
Using fgets is not necessarily problematic, all the gnu manual tells you is that if there's a '\0'-Byte in the file, so will there be in your buffer. You won't be able to tell if the null-delimiter in your buffer is the actual end of the file or just a null within the file. This means you can read a 100 char file into a 200 char buffer and it will contain a 50 char c-string.
The stdio.h readline in fact doesn't appear to have any sane length limitation so fread might be viable alternative.
Unlinke C getline
and C++ std::getline()
, C++ std::istream::getline()
is limited to count
characters
Upvotes: 4