From 2cad542ca939cd42a30f3d0b75f97a14095e3da5 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sun, 4 May 2014 20:41:40 -0400 Subject: cap scrollback to avoid unbounded memory usage --- src/config.c | 4 ++++ src/config.h | 1 + src/screen.c | 34 ++++++++++++++++++++++++++++------ 3 files changed, 33 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/config.c b/src/config.c index 3a4ae4a..689f042 100644 --- a/src/config.c +++ b/src/config.c @@ -312,6 +312,7 @@ static void runes_config_set_defaults(RunesTerm *t) config->default_cols = 80; config->scroll_lines = 3; + config->scrollback_length = 4096; } static FILE *runes_config_get_config_file() @@ -499,6 +500,9 @@ static void runes_config_set(RunesTerm *t, char *key, char *val) else if (!strcmp(key, "scroll_lines")) { config->scroll_lines = runes_config_parse_uint(val); } + else if (!strcmp(key, "scrollback_length")) { + config->scrollback_length = runes_config_parse_uint(val); + } else if (!strcmp(key, "command")) { config->cmd = runes_config_parse_string(val); } diff --git a/src/config.h b/src/config.h index a98d9d0..58b781b 100644 --- a/src/config.h +++ b/src/config.h @@ -13,6 +13,7 @@ struct runes_config { int default_cols; int scroll_lines; + int scrollback_length; char *cmd; char *font_name; diff --git a/src/screen.c b/src/screen.c index 3681eb4..86a29c0 100644 --- a/src/screen.c +++ b/src/screen.c @@ -810,13 +810,35 @@ static void runes_screen_scroll_down(RunesTerm *t, int count) } } else { - runes_screen_ensure_capacity(t, scr->grid->row_count + count); - for (i = 0; i < count; ++i) { - row = runes_screen_row_at(t, i + scr->grid->max.row); - row->cells = calloc(scr->grid->max.col, sizeof(struct runes_cell)); + int scrollback = t->config.scrollback_length; + + if (scr->grid->row_count + count > scrollback) { + int overflow = scr->grid->row_count + count - scrollback; + + runes_screen_ensure_capacity(t, scrollback); + for (i = 0; i < overflow; ++i) { + free(scr->grid->rows[i].cells); + } + memmove( + &scr->grid->rows[0], &scr->grid->rows[overflow], + (scrollback - overflow) * sizeof(struct runes_row)); + for (i = scrollback - count; i < scrollback; ++i) { + scr->grid->rows[i].cells = calloc( + scr->grid->max.col, sizeof(struct runes_cell)); + } + scr->grid->row_count = scrollback; + scr->grid->row_top = scrollback - scr->grid->max.row; + } + else { + runes_screen_ensure_capacity(t, scr->grid->row_count + count); + for (i = 0; i < count; ++i) { + row = runes_screen_row_at(t, i + scr->grid->max.row); + row->cells = calloc( + scr->grid->max.col, sizeof(struct runes_cell)); + } + scr->grid->row_count += count; + scr->grid->row_top += count; } - scr->grid->row_count += count; - scr->grid->row_top += count; } } -- cgit v1.2.3-54-g00ecf