getline() vs. fgets(): Control memory allocation

Some coding guidelines (like MISRA C) may prevent you to use dynamic memory allocations (like getline()). There are reasons for that, for example memory leak avoiding.

If you know maximum size of all acceptable lines, then you could avoid memory allocations by using fgets() instead of getline(), and so remove one potential memory leak point.


It can be dangerous, yes. Don’t know how this would work on other computers, but running the code below froze my computer to the point of needing a hard reset:

/* DANGEROUS CODE */

#include <stdio.h>

int main(void)
{
    FILE *f;
    char *s;
    size_t n = 0;

    f = fopen("/dev/zero", "r");
    getline(&s, &n, f);

    return 0;
}

My question is: Isn’t that dangerous? What if by accident or malicious intent someone creates a 100GB file with no '\n' byte in it – won’t that make my getline() call allocate an insane amount of memory?

Yes, what you describe is a plausible risk. However,

  • if the program requires loading an entire line into memory at once, then allowing getline() to attempt to do that is not inherently more risky than writing your own code to do it with fgets(); and
  • if you have a program that has such a vulnerability, then you can mitigate the risk by using setrlimit() to limit the total amount of (virtual) memory it can reserve. This can be used to cause it to fail instead of successfully allocating enough memory to interfere with the rest of the system.

Best overall, I'd argue, is to write code that does not require input in units of full lines (all at once) in the first place, but such an approach has its own complexities.


The getline function uses malloc and realloc internally and returns -1 if they fail, so the result is no different than if you attempted to call malloc(100000000000). Namely, errno gets set to ENOMEM and getline returns -1.

So you would have the same problem whether you used getline or tried to do the same thing with fgets and manual memory allocation to ensure you read a full line.

Tags:

C

Posix