From 9a160509d74c521f2de005e0daf3762866ef8e04 Mon Sep 17 00:00:00 2001 From: Sebastien Helleu Date: Sun, 1 Dec 2013 08:37:22 +0100 Subject: [PATCH] core: fix random crash when closing a buffer The problem happened because we used a pointer to a "struct t_gui_buffer_visited" for the switch to another buffer, when the buffer is closed. This is executed in all windows displaying the buffer, but on each switch to buffer, the visited buffers are updated and therefore the address can change. The pointer becomes invalid, and WeeChat still uses it on next windows for the buffer switch. It happened rarely because the visited buffer is freed and allocated immediately after, so the address is often the same in memory. Thanks to silverd for the tests on OS X to track the problem. --- ChangeLog | 1 + src/gui/gui-buffer.c | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 858e7b39f..8e0263b47 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,7 @@ http://weechat.org/files/releasenotes/ReleaseNotes-devel.html[release notes] == Version 0.4.3 (under dev) +* core: fix random crash when closing a buffer * core: fix crash on /buffer close core.weechat * core: add option "libs" for command /debug * core: apply color attributes when clearing a window (patch #8236) diff --git a/src/gui/gui-buffer.c b/src/gui/gui-buffer.c index daa461ac0..4d08d71c2 100644 --- a/src/gui/gui-buffer.c +++ b/src/gui/gui-buffer.c @@ -2126,6 +2126,7 @@ gui_buffer_close (struct t_gui_buffer *buffer) { struct t_gui_window *ptr_window; struct t_gui_buffer *ptr_buffer, *ptr_back_to_buffer; + struct t_gui_buffer *ptr_buffer_visited_buffer; int index; struct t_gui_buffer_visited *ptr_buffer_visited; @@ -2152,7 +2153,7 @@ gui_buffer_close (struct t_gui_buffer *buffer) * find other buffer to display: previously visited buffer if current * window is displaying buffer, or buffer # - 1 */ - ptr_buffer_visited = NULL; + ptr_buffer_visited_buffer = NULL; if (CONFIG_BOOLEAN(config_look_jump_previous_buffer_when_closing) && gui_current_window && (gui_current_window->buffer == buffer)) { @@ -2160,8 +2161,11 @@ gui_buffer_close (struct t_gui_buffer *buffer) if (index >= 0) { ptr_buffer_visited = gui_buffer_visited_search_by_number (index); - if (ptr_buffer_visited->buffer == buffer) - ptr_buffer_visited = NULL; + if (ptr_buffer_visited + && (ptr_buffer_visited->buffer != buffer)) + { + ptr_buffer_visited_buffer = ptr_buffer_visited->buffer; + } } } @@ -2181,10 +2185,10 @@ gui_buffer_close (struct t_gui_buffer *buffer) ptr_back_to_buffer, 1); } - else if (ptr_buffer_visited) + else if (ptr_buffer_visited_buffer) { gui_window_switch_to_buffer (ptr_window, - ptr_buffer_visited->buffer, + ptr_buffer_visited_buffer, 1); } else if (ptr_window->buffer->prev_buffer)