NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
lib/60153: Curses crash due to missing NULL check
>Number: 60153
>Category: lib
>Synopsis: Curses crash due to missing NULL check
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Tue Mar 31 23:00:00 +0000 2026
>Originator: Harold Gutch
>Release: 11.0-RC2
>Organization:
The NULLBSD Foundation
>Environment:
NetBSD 11.0_RC2 NetBSD 11.0_RC2 (GENERIC) #0: Sun Mar 8 10:59:15 UTC 2026 mkrepro%mkrepro.NetBSD.org@localhost:/usr/src/sys/arch/i386/compile/GENERIC i386
>Description:
For a while our curses was stricter than other implementations and crashed it was used with a NULL pointer for the window argument. On Dec 23, blymn committed some NULL guards so that applications doing violating the spec would no longer crash (and we would get blame for their bugs). One such check accidentally ended up under a #ifdef DEBUG and there is software out there that triggers this bug.
>How-To-Repeat:
Install NetBSD/i386 11.0-RC2, set up pkgin, install the profanity-0.14.0nb19 package and start profanity. Observe profanity segfaulting.
This bug should apply just the same to current, it was merely observed on 11.0-RC2. NetBSD 10 doesn't have any of the NULL guards, so I don't consider this affected by this (even if profanity will probably crash just the same there - untested!).
>Fix:
Patch against -current (not netbsd-11). The snippet that fixes this one crash is the 2nd chunk in the patch against lib/libcurses/addbytes.c which moves the if (__predict_false(win == NULL)) check out of the #ifdef DEBUG . But while here I decided to move everything that dereferences the pointer in question (mostly "win") to after the NULL check. The dereferences in variable declarations additionally violate KNF ("Avoid initializing variables in the declarations"). I didn't clean up the other KNF violations, only the ones related to this bug.
Note that ultimately this is a bug not in our curses but in profanity. That should also be fixed.
index f4698c4a9d2e..60f955227d79 100644
--- a/lib/libcurses/add_wch.c
+++ b/lib/libcurses/add_wch.c
@@ -92,12 +92,13 @@ mvwadd_wch(WINDOW *win, int y, int x, const cchar_t *wch)
int
wadd_wch(WINDOW *win, const cchar_t *wch)
{
- int y = win->cury;
+ int y;
__LINE *lnp = NULL;
if (__predict_false(win == NULL))
return ERR;
+ y = win->cury;
#ifdef DEBUG
int i;
int x = win->curx;
diff --git a/lib/libcurses/addbytes.c b/lib/libcurses/addbytes.c
index da0590328485..62c4bbef5ae5 100644
--- a/lib/libcurses/addbytes.c
+++ b/lib/libcurses/addbytes.c
@@ -115,7 +115,7 @@ int
_cursesi_waddbytes(WINDOW *win, const char *bytes, int count, attr_t attr,
int char_interp)
{
- int *py = &win->cury, *px = &win->curx, err;
+ int *py, *px, err;
__LINE *lp;
#ifdef HAVE_WCHAR
int n;
@@ -127,10 +127,12 @@ _cursesi_waddbytes(WINDOW *win, const char *bytes, int count, attr_t attr,
#endif
#ifdef DEBUG
int i;
+#endif
if (__predict_false(win == NULL))
return ERR;
+#ifdef DEBUG
for (i = 0; i < win->maxy; i++) {
assert(win->alines[i]->sentinel == SENTINEL_VALUE);
}
@@ -138,6 +140,8 @@ _cursesi_waddbytes(WINDOW *win, const char *bytes, int count, attr_t attr,
__CTRACE(__CTRACE_INPUT, "ADDBYTES: add %d bytes\n", count);
#endif
+ py = &win->cury;
+ px = &win->curx;
err = OK;
lp = win->alines[*py];
@@ -351,7 +355,7 @@ _cursesi_addwchar(WINDOW *win, __LINE **lnp, int *y, int *x,
return ERR;
#else
int sx = 0, ex = 0, cw = 0, i = 0, newx = 0, tabsize;
- __LDATA *lp = &win->alines[*y]->line[*x], *tp = NULL;
+ __LDATA *lp, *tp = NULL;
nschar_t *np = NULL;
cchar_t cc;
attr_t attributes;
@@ -359,6 +363,8 @@ _cursesi_addwchar(WINDOW *win, __LINE **lnp, int *y, int *x,
if (__predict_false(win == NULL))
return ERR;
+ lp = &win->alines[*y]->line[*x];
+
if (char_interp) {
/* special characters handling */
switch (wch->vals[0]) {
diff --git a/lib/libcurses/attributes.c b/lib/libcurses/attributes.c
index 51eb61749f5c..96686f6027f7 100644
--- a/lib/libcurses/attributes.c
+++ b/lib/libcurses/attributes.c
@@ -221,9 +221,9 @@ wattr_set(WINDOW *win, attr_t attr, short pair, void *opts)
int
wcolor_set(WINDOW *win, short pair, void *opts)
{
- __CTRACE(__CTRACE_COLOR, "wolor_set: win %p, pair %d\n", win, pair);
+ __CTRACE(__CTRACE_COLOR, "wcolor_set: win %p, pair %d\n", win, pair);
- if (__predict_false(opts != NULL))
+ if ((__predict_false(win == NULL)) || (__predict_false(opts != NULL)))
return ERR;
__wcolor_set(win, (attr_t) COLOR_PAIR(pair));
diff --git a/lib/libcurses/insdelln.c b/lib/libcurses/insdelln.c
index eeea930d4fe9..e8861330a133 100644
--- a/lib/libcurses/insdelln.c
+++ b/lib/libcurses/insdelln.c
@@ -76,7 +76,7 @@ winsdelln(WINDOW *win, int nlines)
attr_t attr;
__CTRACE(__CTRACE_LINE,
- "winsdelln: (%p) cury=%d lines=%d\n", win, win->cury, nlines);
+ "winsdelln: (%p) cury=%d lines=%d\n", win, (win != NULL) ? win->cury : 0, nlines);
if (__predict_false(win == NULL))
return ERR;
diff --git a/lib/libcurses/refresh.c b/lib/libcurses/refresh.c
index 10f4fd0ccf65..2015ff2b1fe0 100644
--- a/lib/libcurses/refresh.c
+++ b/lib/libcurses/refresh.c
@@ -104,7 +104,7 @@ pnoutrefresh(WINDOW *pad, int pbegy, int pbegx, int sbegy, int sbegx,
int pmaxy, pmaxx;
__CTRACE(__CTRACE_REFRESH, "pnoutrefresh: pad %p, flags 0x%08x\n",
- pad, pad->flags);
+ pad, (pad != NULL) ? pad->flags : 0);
__CTRACE(__CTRACE_REFRESH,
"pnoutrefresh: (%d, %d), (%d, %d), (%d, %d)\n",
pbegy, pbegx, sbegy, sbegx, smaxy, smaxx);
@@ -150,7 +150,7 @@ static int
_wnoutrefresh(WINDOW *win, int begy, int begx, int wbegy, int wbegx,
int maxy, int maxx)
{
- SCREEN *screen = win->screen;
+ SCREEN *screen;
short sy, wy, wx, y_off, x_off, mx, dy_off, dx_off, endy;
int newy, newx;
#ifdef HAVE_WCHAR
@@ -161,7 +161,7 @@ _wnoutrefresh(WINDOW *win, int begy, int begx, int wbegy, int wbegx,
WINDOW *sub_win, *orig, *swin, *dwin;
__CTRACE(__CTRACE_REFRESH, "_wnoutrefresh: win %p, flags 0x%08x\n",
- win, win->flags);
+ win, (win != NULL) ? win->flags : 0);
__CTRACE(__CTRACE_REFRESH,
"_wnoutrefresh: (%d, %d), (%d, %d), (%d, %d)\n",
begy, begx, wbegy, wbegx, maxy, maxx);
@@ -169,6 +169,8 @@ _wnoutrefresh(WINDOW *win, int begy, int begx, int wbegy, int wbegx,
if (__predict_false(win == NULL))
return ERR;
+ screen = win->screen;
+
if (screen->curwin)
return OK;
@@ -515,7 +517,7 @@ prefresh(WINDOW *pad, int pbegy, int pbegx, int sbegy, int sbegx,
int retval;
__CTRACE(__CTRACE_REFRESH, "prefresh: pad %p, flags 0x%08x\n",
- pad, pad->flags);
+ pad, (pad != NULL) ? pad->flags : 0);
if (__predict_false(pad == NULL))
return ERR;
diff --git a/lib/libcurses/touchwin.c b/lib/libcurses/touchwin.c
index 9c074b3d0536..7043db90da22 100644
--- a/lib/libcurses/touchwin.c
+++ b/lib/libcurses/touchwin.c
@@ -110,7 +110,7 @@ is_wintouched(WINDOW *win)
int y, maxy;
__CTRACE(__CTRACE_LINE, "is_wintouched: (%p, maxy %d)\n", win,
- win->maxy);
+ (win != NULL) ? win->maxy : 0);
if (__predict_false(win == NULL))
return FALSE;
Home |
Main Index |
Thread Index |
Old Index