On Mon, Nov 13, 2023 at 02:54:06PM +0100, наб wrote: > Package: libncurses6 > Version: 6.4-4 > Severity: normal > Tags: patch ... > I see "while ((*str != '\0') && (n-- > 0)) {" is in the wrong order, > and ought to be "(n-- > 0) && (*str != '\0')" ‒ only reading from str > when it's not past the end.
It's a little more complicated than that. The problem was introduced here: 20201205 + eliminate an additional strlen and wsclen. + eliminate an unnecessary strlen in waddnstr() (suggested by Benjamin Abendroth). The null terminator should be checked only for the special case where the passed-in length is negative. I overlooked this case when eliminating the strlen's. Here's what I have in mind (using a flag to short-circuit past the test for null terminator): diff -u -r1.58 lib_addstr.c --- lib_addstr.c 2022/06/11 20:12:04 1.58 +++ lib_addstr.c 2023/11/14 01:09:13 @@ -55,16 +55,18 @@ T((T_CALLED("waddnstr(%p,%s,%d)"), (void *) win, _nc_visbufn(astr, n), n)); - if (win && (str != 0)) { + if (win && (str != 0) && (n != 0)) { + bool explicit = (n > 0); + TR(TRACE_VIRTPUT | TRACE_ATTRS, ("... current %s", _traceattr(WINDOW_ATTRS(win)))); code = OK; TR(TRACE_VIRTPUT, ("str is not null, length = %d", - ((n > 0) ? n : (int) strlen(str)))); - if (n < 0) + (explicit ? n : (int) strlen(str)))); + if (!explicit) n = INT_MAX; - while ((*str != '\0') && (n-- > 0)) { + while ((explicit || (*str != '\0')) && (n-- > 0)) { NCURSES_CH_T ch; TR(TRACE_VIRTPUT, ("*str = %#o", UChar(*str))); SetChar(ch, UChar(*str++), A_NORMAL); @@ -228,16 +230,18 @@ T((T_CALLED("waddnwstr(%p,%s,%d)"), (void *) win, _nc_viswbufn(str, n), n)); - if (win && (str != 0)) { + if (win && (str != 0) && (n != 0)) { + bool explicit = (n > 0); + TR(TRACE_VIRTPUT | TRACE_ATTRS, ("... current %s", _traceattr(WINDOW_ATTRS(win)))); code = OK; TR(TRACE_VIRTPUT, ("str is not null, length = %d", - ((n > 0) ? n : (int) wcslen(str)))); - if (n < 0) + (explicit ? n : (int) wcslen(str)))); + if (!explicit) n = INT_MAX; - while ((*str != L('\0')) && (n-- > 0)) { + while ((explicit || (*str != L('\0'))) && (n-- > 0)) { NCURSES_CH_T ch; TR(TRACE_VIRTPUT, ("*str[0] = %#lx", (unsigned long) *str)); SetChar(ch, *str++, A_NORMAL); -- Thomas E. Dickey <dic...@invisible-island.net> https://invisible-island.net
signature.asc
Description: PGP signature