From 0437af53c3372855c969106a7406a50928bde51e Mon Sep 17 00:00:00 2001 From: cowmonk Date: Tue, 21 Jan 2025 13:21:16 -0700 Subject: [PATCH] Fixing (potentially) a buffer underflow in key_press_cb Basically the inputs are goofy --- cowterm.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/cowterm.c b/cowterm.c index 810b7e9..50b2e1a 100644 --- a/cowterm.c +++ b/cowterm.c @@ -304,6 +304,10 @@ static void draw_char(Display *display, Drawable d, int x, int y) { if (x < 0 || x >= term_cols || y < 0 || y >= term_rows) return; + char c = terminal_buffer[y][x]; + if (c < 32 || c > 126) // Only allow printable ASCII characters + return; + unsigned long fg = color_buffer[y][x]; unsigned long bg = bg_color_buffer[y][x]; int attr = attr_buffer[y][x]; @@ -328,7 +332,7 @@ static void draw_char(Display *display, Drawable d, int x, int y) { XSetForeground(display, gc, fg); - char c[2] = {terminal_buffer[y][x], '\0'}; + char str[2] = {c, '\0'}; XFontStruct *font = regular_font; if (attr & ATTR_BOLD) @@ -337,7 +341,8 @@ static void draw_char(Display *display, Drawable d, int x, int y) { font = italic_font; XSetFont(display, gc, font->fid); - XDrawString(display, d, gc, x * CHAR_WIDTH, (y + 1) * CHAR_HEIGHT - 4, c, 1); + XDrawString(display, d, gc, x * CHAR_WIDTH, (y + 1) * CHAR_HEIGHT - 4, str, + 1); } static void draw_terminal(Display *display, Window window) { @@ -785,6 +790,46 @@ static void parse_ansi_code(const char *buf, int *idx, int max_len, switch (buf[*idx]) { case 'H': // Set cursor position + if (param_idx >= 2) { + cursor_y = params[0] - 1 < 0 ? 0 + : params[0] - 1 >= term_rows ? term_rows - 1 + : params[0] - 1; + cursor_x = params[1] - 1 < 0 ? 0 + : params[1] - 1 >= term_cols ? term_cols - 1 + : params[1] - 1; + } else { + cursor_x = cursor_y = 0; + } + break; + case 's': // Save cursor position + if (param_idx == 0) { + saved_cursor_x = cursor_x; + saved_cursor_y = cursor_y; + } + break; + case 'u': // Restore cursor position + if (param_idx == 0) { + cursor_x = saved_cursor_x; + cursor_y = saved_cursor_y; + } + break; + case 'h': // Set mode + case 'l': // Reset mode + if (param_idx >= 1) { + switch (params[0]) { + case 25: // Show/hide cursor + cursor_visible = (buf[*idx] == 'h'); + needs_refresh = 1; + break; + case 12: // Start/stop blinking cursor + cursor_visible = 1; + needs_refresh = 1; + break; + default: + break; + } + } + break; case 'f': // Alternative set cursor position if (param_idx >= 2) { cursor_y = params[0] - 1 < 0 ? 0 @@ -1062,8 +1107,11 @@ static void key_press_cb(XKeyEvent *event, void *data) { write(*master, "\025", 1); return; } - char ctrl_char = '@' + (keysym & 0x1f); - write(*master, &ctrl_char, 1); + if ((keysym & 0x1f) >= '@' && (keysym & 0x1f) <= '_') { + char ctrl_char = '@' + (keysym & 0x1f); + write(*master, &ctrl_char, 1); + return; + } return; } @@ -1071,10 +1119,6 @@ static void key_press_cb(XKeyEvent *event, void *data) { write(*master, "\r", 1); // Shell handles return } else if (keysym == XK_BackSpace) { write(*master, "\177", 1); // Shell handles backspace - } else if (cursor_y > 0) { - char seq[8]; - snprintf(seq, sizeof(seq), "\033[A\033[%dC", term_cols); - write(*master, seq, strlen(seq)); } else if (keysym == XK_Left) { if (cursor_x > 0) { write(*master, "\033[D", 3); @@ -1098,6 +1142,8 @@ static void key_press_cb(XKeyEvent *event, void *data) { } else if (keysym == XK_Tab) { write(*master, "\t", 1); // Shell handles autocomplete } else if (len > 0) { + if (len > (int)sizeof(buf)) + len = sizeof(buf); write(*master, buf, len); if (cursor_x >= term_cols - 1) { write(*master, "\r\n", 2); @@ -1236,8 +1282,9 @@ int main(void) { needs_refresh = 1; break; case KeyPress: - if (!(ev.xkey.state & ControlMask) && ev.xkey.keycode < 128) + if (ev.xkey.keycode < 128) { key_press_cb(&ev.xkey, &master); + } break; case Expose: needs_refresh = 1;