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

Attachment: signature.asc
Description: PGP signature

Reply via email to