Skip to content

Commit 3ddbea7

Browse files
npitregregkh
authored andcommitted
vt: resize saved unicode buffer on alt screen exit after resize
Instead of discarding the saved unicode buffer when the console was resized while in the alternate screen, resize it to the current dimensions using vc_uniscr_copy_area() to preserve its content. This properly restores the unicode screen on alt screen exit rather than lazily rebuilding it from a lossy reverse glyph translation. On allocation failure the stale buffer is freed and vc_uni_lines is set to NULL so it gets lazily rebuilt via vc_uniscr_check() when next needed. Fixes: 4001449 ("vt: discard stale unicode buffer on alt screen exit after resize") Cc: stable <stable@kernel.org> Signed-off-by: Nicolas Pitre <nico@fluxnic.net> Link: https://patch.msgid.link/3nsr334n-079q-125n-7807-n4nq818758ns@syhkavp.arg Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 4001449 commit 3ddbea7

1 file changed

Lines changed: 15 additions & 9 deletions

File tree

drivers/tty/vt/vt.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1901,7 +1901,6 @@ static void leave_alt_screen(struct vc_data *vc)
19011901
unsigned int rows = min(vc->vc_saved_rows, vc->vc_rows);
19021902
unsigned int cols = min(vc->vc_saved_cols, vc->vc_cols);
19031903
u16 *src, *dest;
1904-
bool uni_lines_stale;
19051904

19061905
if (vc->vc_saved_screen == NULL)
19071906
return; /* Not inside an alt-screen */
@@ -1912,16 +1911,23 @@ static void leave_alt_screen(struct vc_data *vc)
19121911
}
19131912
/*
19141913
* If the console was resized while in the alternate screen,
1915-
* vc_saved_uni_lines was allocated for the old dimensions.
1916-
* Restoring it would cause out-of-bounds accesses. Discard it
1917-
* and let the unicode screen be lazily rebuilt.
1914+
* resize the saved unicode buffer to the current dimensions.
1915+
* On allocation failure new_uniscr is NULL, causing the old
1916+
* buffer to be freed and vc_uni_lines to be lazily rebuilt
1917+
* via vc_uniscr_check() when next needed.
19181918
*/
1919-
uni_lines_stale = vc->vc_saved_rows != vc->vc_rows ||
1920-
vc->vc_saved_cols != vc->vc_cols;
1921-
if (uni_lines_stale)
1919+
if (vc->vc_saved_uni_lines &&
1920+
(vc->vc_saved_rows != vc->vc_rows ||
1921+
vc->vc_saved_cols != vc->vc_cols)) {
1922+
u32 **new_uniscr = vc_uniscr_alloc(vc->vc_cols, vc->vc_rows);
1923+
1924+
if (new_uniscr)
1925+
vc_uniscr_copy_area(new_uniscr, vc->vc_cols, vc->vc_rows,
1926+
vc->vc_saved_uni_lines, cols, 0, rows);
19221927
vc_uniscr_free(vc->vc_saved_uni_lines);
1923-
else
1924-
vc_uniscr_set(vc, vc->vc_saved_uni_lines);
1928+
vc->vc_saved_uni_lines = new_uniscr;
1929+
}
1930+
vc_uniscr_set(vc, vc->vc_saved_uni_lines);
19251931
vc->vc_saved_uni_lines = NULL;
19261932
restore_cur(vc);
19271933
/* Update the entire screen */

0 commit comments

Comments
 (0)