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>
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: