From 8abe53cf4850955f9cc9ce1b3b1305f209d7858c Mon Sep 17 00:00:00 2001 From: "Vladimir D. Seleznev" Date: Thu, 12 Sep 2019 21:12:25 +0300 Subject: [PATCH] ALT Fix CVE-2018-20786 Fix crash when out of memory while opening a terminal window. Based on cd929f7ba8cc5b6d6dcf35c8b34124e969fed6b8 of https://github.com/vim/vim. --- libvert/src/screen.c | 25 ++++++++++++++++--------- libvert/src/state.c | 9 +++++++++ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/libvert/src/screen.c b/libvert/src/screen.c index 8cb8c46..f305dad 100644 --- a/libvert/src/screen.c +++ b/libvert/src/screen.c @@ -94,8 +94,7 @@ static ScreenCell *realloc_buffer(VTermScreen *screen, ScreenCell *buffer, int n } } - if(buffer) - vterm_allocator_free(screen->vt, buffer); + vterm_allocator_free(screen->vt, buffer); return new_buffer; } @@ -517,8 +516,7 @@ static int resize(int new_rows, int new_cols, VTermPos *delta, void *user) screen->rows = new_rows; screen->cols = new_cols; - if(screen->sb_buffer) - vterm_allocator_free(screen->vt, screen->sb_buffer); + vterm_allocator_free(screen->vt, screen->sb_buffer); screen->sb_buffer = vterm_allocator_malloc(screen->vt, sizeof(VTermScreenCell) * new_cols); @@ -619,13 +617,20 @@ static VTermStateCallbacks state_cbs = { .setlineinfo = &setlineinfo, }; +/* + * Allocate a new screen and return it. + * Return NULL when out of memory. + */ static VTermScreen *screen_new(VTerm *vt) { VTermState *state = vterm_obtain_state(vt); - if(!state) + if (state == NULL) return NULL; VTermScreen *screen = vterm_allocator_malloc(vt, sizeof(VTermScreen)); + if (screen == NULL) + return NULL; + int rows, cols; vterm_get_size(vt, &rows, &cols); @@ -648,6 +653,11 @@ static VTermScreen *screen_new(VTerm *vt) screen->buffer = screen->buffers[0]; screen->sb_buffer = vterm_allocator_malloc(screen->vt, sizeof(VTermScreenCell) * cols); + if (screen->buffer == NULL || screen->sb_buffer == NULL) + { + vterm_screen_free(screen); + return NULL; + } vterm_state_set_callbacks(screen->state, &state_cbs, screen); @@ -657,11 +667,8 @@ static VTermScreen *screen_new(VTerm *vt) INTERNAL void vterm_screen_free(VTermScreen *screen) { vterm_allocator_free(screen->vt, screen->buffers[0]); - if(screen->buffers[1]) - vterm_allocator_free(screen->vt, screen->buffers[1]); - + vterm_allocator_free(screen->vt, screen->buffers[1]); vterm_allocator_free(screen->vt, screen->sb_buffer); - vterm_allocator_free(screen->vt, screen); } diff --git a/libvert/src/state.c b/libvert/src/state.c index 68cc4f6..ad61c90 100644 --- a/libvert/src/state.c +++ b/libvert/src/state.c @@ -52,6 +52,8 @@ static VTermState *vterm_state_new(VTerm *vt) { VTermState *state = vterm_allocator_malloc(vt, sizeof(VTermState)); + if (state == NULL) + return NULL; state->vt = vt; state->rows = vt->rows; @@ -1665,12 +1667,19 @@ static const VTermParserCallbacks parser_callbacks = { .resize = on_resize, }; +/* + * Return the existing state or create a new one. + * Returns NULL when out of memory. + */ VTermState *vterm_obtain_state(VTerm *vt) { if(vt->state) return vt->state; VTermState *state = vterm_state_new(vt); + if (state == NULL) + return NULL; + vt->state = state; state->combine_chars_size = 16; -- 2.21.0