libc/stdio: allocate a buffer in getdelim() when *lineptr is NULL

POSIX requires getdelim()/getline() to allocate a new buffer whenever
*lineptr is NULL, regardless of the value of *n.  The previous code read
the buffer size from *n unconditionally and only fell back to the initial
size when *n was zero, so a caller that passes *lineptr == NULL together
with an uninitialized (non-zero) *n caused lib_malloc() to be invoked with
that garbage size and typically fail with ENOMEM.

Treat a NULL *lineptr the same as a zero *n: (re)allocate from the known
BUFSIZE_INIT and ignore the untrusted *n.  This matches the glibc
behaviour that portable code relies on (for example toybox grep, which
calls getdelim() with an uninitialized size variable).

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
Xiang Xiao 2026-07-25 00:08:37 +08:00 • committed by archer
parent af65d2e04a
commit fa1bbce9c9

View file

@ -99,10 +99,14 @@ ssize_t getdelim(FAR char **lineptr, size_t *n, int delimiter,
goto errout;
}
/* Verify the buffer size */
/* Verify the buffer size. POSIX requires that a NULL *lineptr be
* (re)allocated regardless of the value of *n, so do not trust *n when
* there is no buffer: a caller may legitimately pass *lineptr == NULL with
* an uninitialized *n.
*/
bufsize = *n;
if (bufsize == 0)
if (*lineptr == NULL || bufsize == 0)
{
/* Pick an initial buffer size */