cmemoryiogetline

Is it unsafe to use getline() in c to read from stdin?


I know that an incorrect use of scanf() to read user input can lead to undefined behavior and potentially security holes in a program. I've seen many people suggesting that is better to use fgets() instead of scanf(), but I know that getline() automatically realloc whenever the line you are trying to read is larger than the buffer. The only case I can think about getline() being unsafe is when the user sends too long a string to stdin so it attempts to allocate more memory than the OS can. I'm a little bit confused about this. Is that why people seem to prefer fgets() over getline() or it has nothing to do with it?

I haven't tried this in code. I just want to hear what experienced people think about this.


Solution

  • Here is an example program:

    #define _POSIX_C_SOURCE 200809L
    #include <stdio.h>
    
    int main() {
        char *lineptr = NULL;
        size_t n;
        if(getline(&lineptr, &n, stdin) == -1) 
            perror("");
    }
    

    if you send 1 TB line to it then it will be killed when the system is out of memory (oom):

    $ dd if=/dev/zero of=/dev/stdout bs=$((1024)) count=$((1024*1024*1024)) | ./a.out
    Killed
    

    Here is the corresponding dmesg log:

    [855440.629377] Out of memory: Killed process 1387599 (a.out) total-vm:134252960kB, anon-rss:55714256kB, file-rss:1164kB, shmem-rss:0kB, UID:1000 pgtables:229544kB oom_score_adj:0
    

    I was playing a Youtube video while this running and there were a few audio glitches but otherwise no ill effects were observed. I have 64 GB of memory and 64 GB of swap configured on a SSD. If you swap to a hard-drive you may be less fortunate.

    You can impose a smaller limit (1 GB) with for example ulimit by either limiting the data seg size (-d) or virtual memory (-v):

    $ ulimit -d $((1024*1024))
    $ dd if=/dev/zero of=/dev/stdout bs=$((1024)) count=$((1024*1024*1024)) | ./a.out 
    Cannot allocate memory