Fixing (potentially) a buffer underflow in key_press_cb

Basically the inputs are goofy
This commit is contained in:
cowmonk 2025-01-21 13:21:16 -07:00
parent 9215edb1c1
commit 0437af53c3

View File

@ -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;