[PATCH] nss_readline: move the NUL terminator along with leading-whitespace strip
Ekalabya Ghosh
ekalabya2010@gmail.com
Sat Sep 26 03:18:02 GMT 2026
From: Ekalabya Ghosh <ekalabya2010@gmail.com>
Date: Sat, 26 Sep 2026 08:47:45 +0530
Subject: [PATCH] nss_readline: move the NUL terminator along with
leading-whitespace strip
__nss_readline() strips leading whitespace from a freshly-read
database line by moving the remainder forward with
"memmove (buf, p, strlen (p))". This moves the line's content but
not its NUL terminator, which stays behind at its original, farther
right position (the line's original, pre-strip length). The bytes
between the newly shortened content and that stale terminator are the
tail end of the original (pre-shift) line -- since the memmove only
overwrites strlen (p) bytes starting at buf, positions at or beyond
that offset keep whatever was already there, and the real terminator
is further right than that. Reading the returned buffer back (e.g.
via strlen) therefore includes those leftover bytes, appended after
the line's own content.
Concretely: for the two-space-indented line " hello\n" in an
8-plus-byte buffer, after stripping the leading whitespace the
intended result is "hello\n" (6 bytes), but the buffer's terminator
stays at its original offset (8), so bytes 6-7 -- which happen to
still hold "o\n", the tail of the pre-strip line -- are included,
and the caller sees "hello\no\n" (8 bytes) instead.
This affects the last line of any nss_files-backed database
(passwd, group, hosts, etc.) that has leading whitespace, appending
extra, leftover bytes from the original line to the value the caller
receives. It stays within the buffer (bounded by the earlier
"buf[len - 1] == '\xff'" truncation check), so this is a
data-correctness bug, not a memory-safety one.
Move strlen (p) + 1 bytes instead, so the NUL terminator moves with
the content it terminates, landing at the correct offset and leaving
no stale bytes in between.
Verified in an isolated harness extracting this exact code block: with
a reused buffer whose tail (beyond the true line length) still held
data from a previous iteration, the unfixed code returned 8 bytes
including that leftover tail; the fixed code returns exactly the
intended 6.
I was not able to build the full glibc tree in the environment I
found this in (glibc's build takes a base image / bootstrap toolchain
this sandbox doesn't have), so this is verified against the extracted
logic rather than the actual compiled __nss_readline, and I have not
run the existing nss test suite -- please double check with that as
part of review.
Signed-off-by: Ekalabya Ghosh <ekalabya2010@gmail.com>
---
nss/nss_readline.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/nss/nss_readline.c b/nss/nss_readline.c
index 08583e9d..fb0689cb 100644
--- a/nss/nss_readline.c
+++ b/nss/nss_readline.c
@@ -71,7 +71,13 @@ __nss_readline (FILE *fp, char *buf, size_t len, off64_t
*poffset)
/* Skip empty lines and comments. */
continue;
if (p != buf)
- memmove (buf, p, strlen (p));
+ /* Move the NUL terminator along with the line content. Moving
+ only strlen (p) bytes leaves the previous (now stale) NUL
+ terminator in its old, farther-right position, so the bytes
+ between the newly shortened line and that old terminator
+ -- leftover from the un-shifted tail of the original line --
+ are included in the result returned to the caller. */
+ memmove (buf, p, strlen (p) + 1);
/* Return line to the caller. */
return 0;
--
2.43.0
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20260925/a781a4ca/attachment-0001.htm>
More information about the Libc-alpha
mailing list