NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
lib/60500: lib/curses: _cursesi_copy_nsp() dereferences a NULL pointer copying a background with combining characters
>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:
Home |
Main Index |
Thread Index |
Old Index