Fixing (potentially) a buffer underflow in key_press_cb
Basically the inputs are goofy
This commit is contained in:
parent
9215edb1c1
commit
0437af53c3
65
cowterm.c
65
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user