mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
console: fix cell overflow
Linux terminal behavior (coming from vt100 I think) is somewhat strange when it comes to line wraps: When a character is printed to the last char cell of a line the cursor does NOT jump to the next line but stays where it is. The line feed happens when the next character is printed. So the valid range for the cursor position is not 0 .. width-1 but 0 .. width, where x == width represents the state where the line is full but the cursor didn't jump to the next line yet. The code for the 'clear from start of line' control sequence (ESC[1K) fails to handle this corner case correctly and may call console_clear_xy() with x == width. That will incorrectly clear the first char cell of the next line, or in case the cursor happens to be on the last line overflow the cell buffer by one character (three bytes). Add a check to the loop to fix that. Didn't spot any other places with the same problem. But it's easy to miss that corner case, so also allocate one extra cell as precaution, so in case we have simliar issues lurking elsewhere it at least wouldn't be a buffer overflow. v2: squashed in additional checks suggested by Christophe de Dinechin. Reported-by: Alexander Oleinik <alxndr@bu.edu> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Christophe de Dinechin <dinechin@redhat.com> Message-id: 20190701075301.14165-1-kraxel@redhat.com
This commit is contained in:
parent
506179e421
commit
5b8541c6c7
1 changed files with 8 additions and 2 deletions
10
ui/console.c
10
ui/console.c
|
@ -484,7 +484,7 @@ static void text_console_resize(QemuConsole *s)
|
|||
if (s->width < w1)
|
||||
w1 = s->width;
|
||||
|
||||
cells = g_new(TextCell, s->width * s->total_height);
|
||||
cells = g_new(TextCell, s->width * s->total_height + 1);
|
||||
for(y = 0; y < s->total_height; y++) {
|
||||
c = &cells[y * s->width];
|
||||
if (w1 > 0) {
|
||||
|
@ -541,6 +541,9 @@ static void update_xy(QemuConsole *s, int x, int y)
|
|||
y2 += s->total_height;
|
||||
}
|
||||
if (y2 < s->height) {
|
||||
if (x >= s->width) {
|
||||
x = s->width - 1;
|
||||
}
|
||||
c = &s->cells[y1 * s->width + x];
|
||||
vga_putcharxy(s, x, y2, c->ch,
|
||||
&(c->t_attrib));
|
||||
|
@ -787,6 +790,9 @@ static void console_handle_escape(QemuConsole *s)
|
|||
static void console_clear_xy(QemuConsole *s, int x, int y)
|
||||
{
|
||||
int y1 = (s->y_base + y) % s->total_height;
|
||||
if (x >= s->width) {
|
||||
x = s->width - 1;
|
||||
}
|
||||
TextCell *c = &s->cells[y1 * s->width + x];
|
||||
c->ch = ' ';
|
||||
c->t_attrib = s->t_attrib_default;
|
||||
|
@ -992,7 +998,7 @@ static void console_putchar(QemuConsole *s, int ch)
|
|||
break;
|
||||
case 1:
|
||||
/* clear from beginning of line */
|
||||
for (x = 0; x <= s->x; x++) {
|
||||
for (x = 0; x <= s->x && x < s->width; x++) {
|
||||
console_clear_xy(s, x, s->y);
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue