From b1326334389e78787f87a4c37539ed183578fe83 Mon Sep 17 00:00:00 2001 From: Jocelyn Falempe Date: Mon, 20 Apr 2026 12:48:19 +0200 Subject: [PATCH 1/2] screen: copy the cell content in remove_from_sb() Instead of copying the line pointer from the scrollback buffer, copy the cell content. the line size can be different in the scrollback buffer, because the scrollback is not resized when the terminal is resized. Signed-off-by: Jocelyn Falempe --- src/tsm/tsm-screen.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/tsm/tsm-screen.c b/src/tsm/tsm-screen.c index ca6c454..cafbfc1 100644 --- a/src/tsm/tsm-screen.c +++ b/src/tsm/tsm-screen.c @@ -64,6 +64,7 @@ #include "libtsm.h" #include "libtsm-int.h" #include "shl-llog.h" +#include "shl-macro.h" #include "shl_dlist.h" #define LLOG_SUBSYSTEM "tsm-screen" @@ -238,6 +239,7 @@ static void link_to_scrollback(struct tsm_screen *con, struct line *line) static void remove_from_sb(struct tsm_screen *con, unsigned int num) { struct line *tmp; + int i, copy_len; /* TODO: more sophisticated ageing */ con->age = con->age_cnt; @@ -257,9 +259,22 @@ static void remove_from_sb(struct tsm_screen *con, unsigned int num) con->sb.pos_num = con->sb.count; con->sb.pos = NULL; } - tmp->sb_id = 0; - memcpy(con->lines[num], tmp, sizeof(*tmp)); - free(tmp); + /* + * Copy the cells from the scrollback buffer to the line. scrollback buffer can have a different + * size as current lines, because resizing doesn't resize lines in scrollback buffer. + */ + copy_len = shl_min(tmp->size, con->lines[num]->size); + memcpy(con->lines[num]->cells, tmp->cells, copy_len * sizeof(struct cell)); + for (i = copy_len; i < con->size_x; i++) + screen_cell_init(con, &con->lines[num]->cells[i]); + con->lines[num]->age = con->age_cnt; + + if (con->sel_active && con->sel_start.line == tmp) + con->sel_start.line = con->lines[num]; + if (con->sel_active && con->sel_end.line == tmp) + con->sel_end.line = con->lines[num]; + + line_free(tmp); } if (!con->sb.pos) con->sb.pos_num = con->sb.count; From 7e699c190f7682dc989b00156d184a64bc5d753a Mon Sep 17 00:00:00 2001 From: Jocelyn Falempe Date: Mon, 20 Apr 2026 12:49:01 +0200 Subject: [PATCH 2/2] test: Add test_robustness This checks random screen resize and selection. Signed-off-by: Jocelyn Falempe --- test/test_selection.c | 60 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/test/test_selection.c b/test/test_selection.c index a2e310d..65cdbf1 100644 --- a/test/test_selection.c +++ b/test/test_selection.c @@ -798,6 +798,65 @@ START_TEST(test_screen_copy_lines_sb_scrolled_cut_off) } END_TEST +static void write_random_string(struct tsm_screen *screen, int count) +{ + char str[201]; + int len = rand() % 200; + int i, c; + + for (c = 0; c < count; c++) { + for (i = 0; i < len; i++) + str[i] = ' ' + rand() % 95; + str[len] = '\0'; + write_string(screen, str); + tsm_screen_newline(screen); + } +} + +START_TEST(test_screen_robustness) +{ + struct tsm_screen *screen; + int sb_size = 500; + int size_x, size_y; + int r, i; + char *str = NULL; + + srand(0x12345678); + + r = tsm_screen_new(&screen, NULL, NULL); + ck_assert_int_eq(r, 0); + + r = tsm_screen_resize(screen, 80, 40); + ck_assert_int_eq(r, 0); + + tsm_screen_set_max_sb(screen, sb_size); + + write_random_string(screen, 600); + + for (i = 0; i < 500; i++) { + size_x = 1 + rand() % 100; + size_y = 1 + rand() % 100; + printf("screen size: %dx%d\n", size_x, size_y); + r = tsm_screen_resize(screen, size_x, size_y); + ck_assert_int_eq(r, 0); + tsm_screen_scroll_up(screen, rand() % sb_size); + tsm_screen_scroll_down(screen, rand() % sb_size); + tsm_screen_selection_start(screen, rand() % size_x, rand() % size_y); + tsm_screen_selection_target(screen, rand() % size_x, rand() % size_y); + r = tsm_screen_selection_copy(screen, &str); + ck_assert_int_ge(r, 0); + if (str) { + free(str); + str = NULL; + } + write_random_string(screen, rand() % 100); + } + + tsm_screen_unref(screen); + screen = NULL; +} +END_TEST + TEST_DEFINE_CASE(misc) TEST(test_screen_copy_incomplete) TEST(test_screen_copy_one_cell) @@ -811,6 +870,7 @@ TEST_DEFINE_CASE(misc) TEST(test_screen_copy_lines_sb) TEST(test_screen_copy_lines_sb_scrolled) TEST(test_screen_copy_lines_sb_scrolled_cut_off) + TEST(test_screen_robustness) TEST_END_CASE TEST_DEFINE(