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