NetBSD Problem Report #60500
From storchaka@gmail.com Sat Jul 25 02:30:35 2026
Return-Path: <storchaka@gmail.com>
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 "YR2" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id ED1971A923C
for <gnats-bugs@gnats.NetBSD.org>; Sat, 25 Jul 2026 02:30:34 +0000 (UTC)
Message-Id: <38507cdb-d1c9-48a2-aa74-974ce0268a7f@gmail.com>
Date: Sat, 25 Jul 2026 05:30:29 +0300
From: Serhiy Storchaka <storchaka@gmail.com>
To: gnats-bugs@netbsd.org
Subject: lib/curses: _cursesi_copy_nsp() dereferences a NULL pointer copying a
background with combining characters
X-From4GNATS: "Serhiy Storchaka via gnats" <gnats-admin@NetBSD.org>
>Number: 60500
>Category: lib
>Synopsis: curses: _cursesi_copy_nsp() crashes when a cell gains its first non-spacing character from the background
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Jul 25 02:35:00 +0000 2026
>Originator: Serhiy Storchaka
>Release: NetBSD 10.1
>Environment:
System: NetBSD 10.1 amd64 (GENERIC), libcurses.so.9.1
>Description:
Setting a window background that carries a non-spacing (combining)
character and
then copying it into a cell that has no non-spacing list yet crashes with a
NULL-pointer write.
_cursesi_copy_nsp() (libcurses/curses.c) copies the source non-spacing
list into
ch->nsp, reusing existing nodes and allocating new ones as needed. When the
destination list is empty (ch->nsp == NULL) and the source is non-empty, the
first iteration allocates a node and links it with
pnp->next = tnp;
but pnp is still NULL (it is only set once a node has been processed),
so this
writes through NULL, and ch->nsp is never set.
A window's background carries a non-spacing character after
bkgrndset()/bkgdset()/
bkgd() of a spacing character followed by a combining one; any later
operation
that copies the background into a fresh cell then triggers it (werase(),
wclrtoeol(), waddch(), ...).
>How-To-Repeat:
/* copy_nsp_crash.c
cc copy_nsp_crash.c -lcurses && ./a.out */
#include <curses.h>
#include <locale.h>
int main(void) {
setlocale(LC_ALL, "");
initscr();
cchar_t wch;
wchar_t s[3] = { 0x65, 0x0301, 0 }; /* 'e' + combining acute
U+0301 */
setcchar(&wch, s, A_NORMAL, 0, NULL);
bkgrndset(&wch); /* background cell now carries a
non-spacing char */
werase(stdscr); /* copy the background into every
(empty) cell */
endwin();
return 0;
}
Crashes in _cursesi_copy_nsp(). Under valgrind (against the current
libcurses):
Invalid write of size 8
at _cursesi_copy_nsp
by werase
by main (copy_nsp_crash.c: werase line)
Access not within mapped region at address 0x8
Also observed on NetBSD 10.1 (libcurses.so.9.1), where wbkgrndset()
itself calls
_cursesi_copy_nsp() and crashes there. (Found via CPython's curses module:
window.bkgdset() of a string with a combining character.)
>Fix:
Attach the first allocated node to the destination head when there is no
previous node yet:
--- a/libcurses/curses.c
+++ b/libcurses/curses.c
@@ -94,7 +94,10 @@ _cursesi_copy_nsp(nschar_t *src_nsp, struct __ldata *ch)
if (!tnp)
return ERR;
tnp->ch = np->ch;
- pnp->next = tnp;
+ if (pnp)
+ pnp->next = tnp;
+ else
+ ch->nsp = tnp;
tnp->next = NULL;
pnp = tnp;
tnp = NULL;
With this change the reproducer runs cleanly (valgrind reports no errors).
>Unformatted:
(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.