Manny_Mar
Manny_Mar

Reputation: 398

getline how to limit amount of input as you can with fgets

GNU manual

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

Answers (2)

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

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

Gamification
Gamification

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

Related Questions