[PATCH] libio: null terminate the buffer upon initial allocation in getdelim

Eric Blake eblake@redhat.com
Mon Nov 17 13:09:44 GMT 2025


On Fri, Nov 14, 2025 at 09:25:36PM -0800, Collin Funk wrote:
> Commit 33eff78c8b28adc4963987880e10d96761f2a167 caused issues in nbdkit
> which had code similar to this to get the last line of the file:
> 
>     while (getline (&line, &len, fp) != -1)
>       ;
>     /* Process LINE.  */
> 
> After that commit, line[0] would be equal to '\0' instead of containing
> the last line of the file like before that commit.
> 
> This patch null terminates the buffer upon getdelim/getline's initial
> allocation. This is compatible with previous glibc versions, while also
> protecting the caller from reading uninitialized memory if the file is
> empty, as long as getline/getdelim does the initial allocation.
> ---

Looks like it matches my idea.

> +++ b/libio/tst-getdelim.c
> @@ -51,11 +51,9 @@ do_test (void)
>    xfclose (memstream);
>    free (lineptr);
>  
> -  /* Test that getdelim NUL terminates upon reading an EOF from an empty
> -     file (BZ #28038).  This test fails on glibc 2.42 and earlier.  */
> -  lineptr = xmalloc (1);
> -  lineptr[0] = 'A';
> -  linelen = 1;
> +  /* Test that we null-terminate the buffer upon allocating it (BZ #28038).  */
> +  lineptr = NULL;
> +  linelen = 0;

Does linelen have to be initialized to any paticular value when
lineptr is passed in as NULL?

>    char *file_name;
>    TEST_VERIFY_EXIT (create_temp_file ("tst-getdelim.", &file_name) != -1);
>    FILE *fp = fopen (file_name, "r");
> diff --git a/manual/stdio.texi b/manual/stdio.texi
> index e8f60b09c1..4e5b890cf0 100644
> --- a/manual/stdio.texi
> +++ b/manual/stdio.texi
> @@ -1279,7 +1279,12 @@ @node Line Input
>  POSIX.1-2008.
>  
>  If an error occurs or end of file is reached without any bytes read,
> -@code{getline} returns @code{-1}.
> +@code{getline} returns @code{-1}.  POSIX leaves the contents of
> +@code{*@var{lineptr}} undefined when @code{getline} returns @code{-1}.
> +If the the @glibcadj{} implementation of @code{getline} allocates the

duplicate "the"

> +initial buffer it will null terminate it to prevent the caller from
> +reading uninitialized memory if no characters can be read from
> +@code{stream}.
>  @end deftypefun
>  
>  @deftypefun ssize_t getdelim (char **restrict @var{lineptr}, size_t *restrict @var{n}, int @var{delimiter}, FILE *restrict @var{stream})
> -- 
> 2.51.1
> 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.
Virtualization:  qemu.org | libguestfs.org



More information about the Libc-alpha mailing list