]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
col: fix cur_col underflow on backspace over a wide char
authorAizal Khan <aizumusheer2@gmail.com>
Wed, 1 Jul 2026 13:21:41 +0000 (18:51 +0530)
committerAizal Khan <aizumusheer2@gmail.com>
Wed, 1 Jul 2026 13:21:41 +0000 (18:51 +0530)
The BS handler in handle_not_graphic() subtracts the last stored
character's width from lns->cur_col (a size_t) and only guards against
cur_col == 0. When the last graphic character is double-width and the
column was reset by CR then advanced by a single space, cur_col is 1 and
cur_col -= 2 wraps to SIZE_MAX. That feeds l_max_col and the stored
c_column, so flush_line() sizes count[] as l_max_col + 1 (== 0) and then
memsets sizeof(size_t) * l_max_col bytes and indexes count[SIZE_MAX] --
an out-of-bounds write reachable from stdin under a UTF-8 locale. Clamp
the subtraction so the column cannot go below zero.

Signed-off-by: Aizal Khan <aizumusheer2@gmail.com>
text-utils/col.c

index 286a6f8334831e975ed669308c90f6ec44cad64d..9c0c9acefcc2ce612052cb12040d22312f65b273 100644 (file)
@@ -396,9 +396,12 @@ static int handle_not_graphic(struct col_ctl *ctl, struct col_lines *lns)
        case BS:
                if (lns->cur_col == 0)
                        return 1;       /* can't go back further */
-               if (lns->c)
-                       lns->cur_col -= lns->c->c_width;
-               else
+               if (lns->c) {
+                       if ((size_t) lns->c->c_width <= lns->cur_col)
+                               lns->cur_col -= lns->c->c_width;
+                       else
+                               lns->cur_col = 0;
+               } else
                        lns->cur_col -= 1;
                return 1;
        case CR: