NetBSD Problem Report #60050
From www@netbsd.org Tue Mar 3 01:03:24 2026
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
client-signature RSA-PSS (2048 bits) client-digest SHA256)
(Client CN "mail.netbsd.org", Issuer "R13" (verified OK))
by mollari.NetBSD.org (Postfix) with ESMTPS id 6D6241A9239
for <gnats-bugs@gnats.NetBSD.org>; Tue, 3 Mar 2026 01:03:24 +0000 (UTC)
Message-Id: <20260303010323.649471A923C@mollari.NetBSD.org>
Date: Tue, 3 Mar 2026 01:03:23 +0000 (UTC)
From: kris@tranception.com
Reply-To: kris@tranception.com
To: gnats-bugs@NetBSD.org
Subject: libedit doesn't handle long lines correctly
X-Send-Pr-Version: www-1.0
X-From4GNATS: "kris@tranception.com via gnats" <gnats-admin@NetBSD.org>
>Number: 60050
>Category: lib
>Synopsis: libedit doesn't handle long lines correctly
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Tue Mar 03 01:05:00 +0000 2026
>Last-Modified: Tue Mar 03 15:10:00 +0000 2026
>Originator: Kristofer Peterson
>Release: NetBSD-current
>Organization:
Tranception Limited
>Environment:
>Description:
If the current input line is long (i.e. greater than EL_BUFSIZ which is 1024 bytes), going to a previous history line will only copy the first EL_BUFSIZ characters into the history but still set the length to full buffer, thus including trailing garbage in the history which if one then returns to the current line can then see.
This was first observed in /bin/sh in FreeBSD-15.0 which incorporates libedit under contrib/libedit, the upstream snapshot was 2025-01-03.
I applied the patch against a clean checkout of https://github.com/NetBSD/src, branch trunk, commit d78321bcf99595ead2ef93fe8624f32d4299d430 (HEAD -> trunk); I include the git diff output below.
>How-To-Repeat:
- run /bin/sh interactively (or another application using libedit)
- enter a long line exceeding EL_BUFSIZ (1024) characters
- go to the previous history line (^P in emacs mode, up arrow, etc.)
- go back to the next history line (^N in emacs mode, down arrow, etc.)
- observe the long line is truncated followed by garbage (nulls etc.)
>Fix:
diff --git a/lib/libedit/chared.c b/lib/libedit/chared.c
index e66fed1faae3..a52296e02ca4 100644
--- a/lib/libedit/chared.c
+++ b/lib/libedit/chared.c
@@ -561,7 +561,7 @@ ch_enlargebufs(EditLine *el, size_t addlen)
(el->el_chared.c_redo.lim - el->el_chared.c_redo.buf);
el->el_chared.c_redo.buf = newbuffer;
- if (!hist_enlargebuf(el, sz, newsz))
+ if (!hist_enlargebuf(el, newsz))
return 0;
/* Safe to set enlarged buffer size */
diff --git a/lib/libedit/common.c b/lib/libedit/common.c
index b1756b87235d..eb593c12d686 100644
--- a/lib/libedit/common.c
+++ b/lib/libedit/common.c
@@ -569,7 +569,7 @@ ed_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
if (el->el_history.eventno == 0) { /* save the current buffer
* away */
(void) wcsncpy(el->el_history.buf, el->el_line.buffer,
- EL_BUFSIZ);
+ el->el_history.sz);
el->el_history.last = el->el_history.buf +
(el->el_line.lastchar - el->el_line.buffer);
}
@@ -641,7 +641,7 @@ ed_search_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
}
if (el->el_history.eventno == 0) {
(void) wcsncpy(el->el_history.buf, el->el_line.buffer,
- EL_BUFSIZ);
+ el->el_history.sz);
el->el_history.last = el->el_history.buf +
(el->el_line.lastchar - el->el_line.buffer);
}
diff --git a/lib/libedit/hist.c b/lib/libedit/hist.c
index 19ce1c161722..89ad8c7deaf1 100644
--- a/lib/libedit/hist.c
+++ b/lib/libedit/hist.c
@@ -223,9 +223,13 @@ hist_command(EditLine *el, int argc, const wchar_t **argv)
*/
libedit_private int
/*ARGSUSED*/
-hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz)
+hist_enlargebuf(EditLine *el, size_t newsz)
{
wchar_t *newbuf;
+ const size_t oldsz = el->el_history.sz;
+
+ if (newsz <= oldsz)
+ return 1;
newbuf = el_realloc(el->el_history.buf, newsz * sizeof(*newbuf));
if (!newbuf)
diff --git a/lib/libedit/hist.h b/lib/libedit/hist.h
index 8f5ab08390d2..6d1b7feb3ce8 100644
--- a/lib/libedit/hist.h
+++ b/lib/libedit/hist.h
@@ -74,7 +74,7 @@ libedit_private void hist_end(EditLine *);
libedit_private el_action_t hist_get(EditLine *);
libedit_private int hist_set(EditLine *, hist_fun_t, void *);
libedit_private int hist_command(EditLine *, int, const wchar_t **);
-libedit_private int hist_enlargebuf(EditLine *, size_t, size_t);
+libedit_private int hist_enlargebuf(EditLine *, size_t);
libedit_private wchar_t *hist_convert(EditLine *, int, void *);
#endif /* _h_el_hist */
>Audit-Trail:
From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/60050 CVS commit: src/lib/libedit
Date: Tue, 3 Mar 2026 10:05:17 -0500
Module Name: src
Committed By: christos
Date: Tue Mar 3 15:05:17 UTC 2026
Modified Files:
src/lib/libedit: chared.c common.c hist.c hist.h
Log Message:
PR/60050: Kristofer Peterson: libedit doesn't handle long lines correctly
Fix history resizing, and copying.
To generate a diff of this commit:
cvs rdiff -u -r1.65 -r1.66 src/lib/libedit/chared.c
cvs rdiff -u -r1.51 -r1.52 src/lib/libedit/common.c
cvs rdiff -u -r1.34 -r1.35 src/lib/libedit/hist.c
cvs rdiff -u -r1.23 -r1.24 src/lib/libedit/hist.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
(Contact us)
$NetBSD: query-full-pr,v 1.51 2026/08/10 02:28:17 riastradh Exp $
$NetBSD: gnats_config.sh,v 1.10 2026/05/13 22:00:09 riastradh Exp $
Copyright © 1994-2026
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.