From 480d603eb5de481b9f3df9982f4dd9a35b29e839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Helleu?= Date: Mon, 23 Oct 2023 13:11:02 +0200 Subject: [PATCH] core: fix crash when a custom bar item name is already used by a default bar item (issue #2034) --- ChangeLog.adoc | 1 + ReleaseNotes.adoc | 13 ++++ src/core/wee-config.c | 30 +++++--- src/gui/gui-bar-item-custom.c | 83 ++++++++++++++++----- src/gui/gui-bar-item-custom.h | 1 + src/gui/gui-bar-item.c | 24 ++++++ src/gui/gui-bar-item.h | 1 + tests/unit/gui/test-gui-bar-item-custom.cpp | 1 + tests/unit/gui/test-gui-bar-item.cpp | 15 ++++ 9 files changed, 139 insertions(+), 30 deletions(-) diff --git a/ChangeLog.adoc b/ChangeLog.adoc index b6addc274..f7b727605 100644 --- a/ChangeLog.adoc +++ b/ChangeLog.adoc @@ -15,6 +15,7 @@ For a list of important changes that require manual actions, please look at rele Bug fixes:: + * core: fix crash when a custom bar item name is already used by a default bar item (issue #2034) * core: fix generation of TOTP on Big Endian systems (issue #2021) * irc: move value `-all` at the end of completions for command `/ignore del` * irc: fix memory leak when joining channels with keys diff --git a/ReleaseNotes.adoc b/ReleaseNotes.adoc index 2eab0f32c..365d61a70 100644 --- a/ReleaseNotes.adoc +++ b/ReleaseNotes.adoc @@ -11,6 +11,19 @@ It is recommended to read it when upgrading to a new stable version. + For a complete list of changes, please look at ChangeLog. +[[v4.0.6]] +== Version 4.0.6 (under dev) + +[[v4.0.6_custom_bar_items]] +=== Custom bar items + +Custom bar items must now have a different name than default bar items +(for example the custom bar item name `time` is now forbidden). + +If you have such names in your config, WeeChat will now fail to load them +(this should not happen anyway, since such bar items can not be properly used +and can cause a crash of WeeChat). + [[v4.0.5]] == Version 4.0.5 (2023-09-24) diff --git a/src/core/wee-config.c b/src/core/wee-config.c index c0557586f..98a7bacf2 100644 --- a/src/core/wee-config.c +++ b/src/core/wee-config.c @@ -2195,17 +2195,20 @@ config_weechat_custom_bar_item_read_cb (const void *pointer, void *data, if (!ptr_temp_item) { /* create new temporary custom bar item */ - ptr_temp_item = gui_bar_item_custom_alloc (item_name); - if (ptr_temp_item) + if (gui_bar_item_search_default (item_name) < 0) { - /* add new custom bar item at the end */ - ptr_temp_item->prev_item = last_gui_temp_custom_bar_item; - ptr_temp_item->next_item = NULL; - if (last_gui_temp_custom_bar_item) - last_gui_temp_custom_bar_item->next_item = ptr_temp_item; - else - gui_temp_custom_bar_items = ptr_temp_item; - last_gui_temp_custom_bar_item = ptr_temp_item; + ptr_temp_item = gui_bar_item_custom_alloc (item_name); + if (ptr_temp_item) + { + /* add new custom bar item at the end */ + ptr_temp_item->prev_item = last_gui_temp_custom_bar_item; + ptr_temp_item->next_item = NULL; + if (last_gui_temp_custom_bar_item) + last_gui_temp_custom_bar_item->next_item = ptr_temp_item; + else + gui_temp_custom_bar_items = ptr_temp_item; + last_gui_temp_custom_bar_item = ptr_temp_item; + } } } @@ -2226,6 +2229,13 @@ config_weechat_custom_bar_item_read_cb (const void *pointer, void *data, section->name, option_name, value); } } + else + { + gui_chat_printf (NULL, + _("%sUnable to add custom bar item \"%s\""), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], + item_name); + } free (item_name); diff --git a/src/gui/gui-bar-item-custom.c b/src/gui/gui-bar-item-custom.c index 64065c1fe..ee83480f4 100644 --- a/src/gui/gui-bar-item-custom.c +++ b/src/gui/gui-bar-item-custom.c @@ -439,31 +439,46 @@ gui_bar_item_custom_new (const char *name, const char *conditions, if (gui_bar_item_custom_search (name)) return NULL; + if (gui_bar_item_search_default (name) >= 0) + return NULL; + + option_conditions = NULL; + option_content = NULL; + new_bar_item_custom = NULL; + option_conditions = gui_bar_item_custom_create_option ( name, GUI_BAR_ITEM_CUSTOM_OPTION_CONDITIONS, conditions); if (!option_conditions) - return NULL; + goto error; option_content = gui_bar_item_custom_create_option ( name, GUI_BAR_ITEM_CUSTOM_OPTION_CONTENT, content); if (!option_content) - { - config_file_option_free (option_conditions, 0); - return NULL; - } + goto error; new_bar_item_custom = gui_bar_item_custom_new_with_options ( name, option_conditions, option_content); + if (!new_bar_item_custom) + goto error; + + gui_bar_item_custom_create_bar_item (new_bar_item_custom); + if (!new_bar_item_custom->bar_item) + goto error; + + gui_bar_item_update (name); + + return new_bar_item_custom; + +error: if (new_bar_item_custom) { - gui_bar_item_custom_create_bar_item (new_bar_item_custom); - gui_bar_item_update (name); + gui_bar_item_custom_free (new_bar_item_custom); } else { @@ -472,8 +487,7 @@ gui_bar_item_custom_new (const char *name, const char *conditions, if (option_content) config_file_option_free (option_content, 0); } - - return new_bar_item_custom; + return NULL; } /* @@ -483,12 +497,13 @@ gui_bar_item_custom_new (const char *name, const char *conditions, void gui_bar_item_custom_use_temp_items () { - struct t_gui_bar_item_custom *ptr_temp_item; + struct t_gui_bar_item_custom *ptr_temp_item, *ptr_next_temp_item; int i; - for (ptr_temp_item = gui_temp_custom_bar_items; ptr_temp_item; - ptr_temp_item = ptr_temp_item->next_item) + ptr_temp_item = gui_temp_custom_bar_items; + while (ptr_temp_item) { + ptr_next_temp_item = ptr_temp_item->next_item; for (i = 0; i < GUI_BAR_ITEM_CUSTOM_NUM_OPTIONS; i++) { if (!ptr_temp_item->options[i]) @@ -500,6 +515,20 @@ gui_bar_item_custom_use_temp_items () } } gui_bar_item_custom_create_bar_item (ptr_temp_item); + if (!ptr_temp_item->bar_item) + { + if (ptr_temp_item->prev_item) + (ptr_temp_item->prev_item)->next_item = ptr_temp_item->next_item; + if (ptr_temp_item->next_item) + (ptr_temp_item->next_item)->prev_item = ptr_temp_item->prev_item; + if (gui_temp_custom_bar_items == ptr_temp_item) + gui_temp_custom_bar_items = ptr_temp_item->next_item; + if (last_gui_temp_custom_bar_item == ptr_temp_item) + last_gui_temp_custom_bar_item = ptr_temp_item->prev_item; + gui_bar_item_custom_free_data (ptr_temp_item); + free (ptr_temp_item); + } + ptr_temp_item = ptr_next_temp_item; } /* remove any existing custom bar item */ @@ -534,6 +563,9 @@ gui_bar_item_custom_rename (struct t_gui_bar_item_custom *item, if (gui_bar_item_custom_search (new_name)) return 0; + if (gui_bar_item_search_default (new_name) >= 0) + return 0; + old_name = strdup (item->name); if (!old_name) return 0; @@ -570,6 +602,24 @@ gui_bar_item_custom_rename (struct t_gui_bar_item_custom *item, return 1; } +/* + * Frees data in a custom bar item.* + */ + +void +gui_bar_item_custom_free_data (struct t_gui_bar_item_custom *item) +{ + int i; + + if (item->name) + free (item->name); + for (i = 0; i < GUI_BAR_ITEM_CUSTOM_NUM_OPTIONS; i++) + { + if (item->options[i]) + config_file_option_free (item->options[i], 1); + } +} + /* * Deletes a custom bar item. */ @@ -578,7 +628,6 @@ void gui_bar_item_custom_free (struct t_gui_bar_item_custom *item) { char *name; - int i; if (!item) return; @@ -599,13 +648,7 @@ gui_bar_item_custom_free (struct t_gui_bar_item_custom *item) last_gui_custom_bar_item = item->prev_item; /* free data */ - if (item->name) - free (item->name); - for (i = 0; i < GUI_BAR_ITEM_CUSTOM_NUM_OPTIONS; i++) - { - if (item->options[i]) - config_file_option_free (item->options[i], 1); - } + gui_bar_item_custom_free_data (item); free (item); diff --git a/src/gui/gui-bar-item-custom.h b/src/gui/gui-bar-item-custom.h index df0109ae8..b3d37d7c0 100644 --- a/src/gui/gui-bar-item-custom.h +++ b/src/gui/gui-bar-item-custom.h @@ -69,6 +69,7 @@ extern struct t_gui_bar_item_custom *gui_bar_item_custom_new (const char *name, extern void gui_bar_item_custom_use_temp_items (); extern int gui_bar_item_custom_rename (struct t_gui_bar_item_custom *item, const char *new_name); +extern void gui_bar_item_custom_free_data (struct t_gui_bar_item_custom *item); extern void gui_bar_item_custom_free (struct t_gui_bar_item_custom *item); extern void gui_bar_item_custom_free_all (); diff --git a/src/gui/gui-bar-item.c b/src/gui/gui-bar-item.c index 6b6a05362..8728ec18b 100644 --- a/src/gui/gui-bar-item.c +++ b/src/gui/gui-bar-item.c @@ -97,6 +97,30 @@ gui_bar_item_valid (struct t_gui_bar_item *bar_item) return 0; } +/* + * Searches for a default bar item by name. + * + * Returns index in gui_bar_item_names[], -1 if not found. + */ + +int +gui_bar_item_search_default (const char *item_name) +{ + int i; + + if (!item_name || !item_name[0]) + return -1; + + for (i = 0; i < GUI_BAR_NUM_ITEMS; i++) + { + if (strcmp (gui_bar_item_names[i], item_name) == 0) + return i; + } + + /* default bar item not found */ + return -1; +} + /* * Searches for a bar item by name. */ diff --git a/src/gui/gui-bar-item.h b/src/gui/gui-bar-item.h index 688311918..25514bddc 100644 --- a/src/gui/gui-bar-item.h +++ b/src/gui/gui-bar-item.h @@ -89,6 +89,7 @@ extern char *gui_bar_item_names[]; /* functions */ extern int gui_bar_item_valid (struct t_gui_bar_item *bar_item); +extern int gui_bar_item_search_default (const char *item_name); extern struct t_gui_bar_item *gui_bar_item_search (const char *name); extern int gui_bar_item_used_in_bar (struct t_gui_bar *bar, const char *item_name, diff --git a/tests/unit/gui/test-gui-bar-item-custom.cpp b/tests/unit/gui/test-gui-bar-item-custom.cpp index f3c221851..300989a42 100644 --- a/tests/unit/gui/test-gui-bar-item-custom.cpp +++ b/tests/unit/gui/test-gui-bar-item-custom.cpp @@ -464,6 +464,7 @@ TEST(GuiBarItemCustom, Rename) /* * Tests functions: + * gui_bar_item_custom_free_data * gui_bar_item_custom_free * gui_bar_item_custom_free_all */ diff --git a/tests/unit/gui/test-gui-bar-item.cpp b/tests/unit/gui/test-gui-bar-item.cpp index ec2c09fa0..79109b6a9 100644 --- a/tests/unit/gui/test-gui-bar-item.cpp +++ b/tests/unit/gui/test-gui-bar-item.cpp @@ -53,6 +53,21 @@ TEST(GuiBarItem, Valid) LONGS_EQUAL(0, gui_bar_item_valid (gui_bar_items + 1)); } +/* + * Tests functions: + * gui_bar_item_search_default + */ + +TEST(GuiBarItem, SearchDefault) +{ + LONGS_EQUAL(-1, gui_bar_item_search_default (NULL)); + LONGS_EQUAL(-1, gui_bar_item_search_default ("")); + LONGS_EQUAL(-1, gui_bar_item_search_default ("zzz")); + + CHECK(gui_bar_item_search_default ("scroll") >= 0); + CHECK(gui_bar_item_search_default ("time") >= 0); +} + /* * Tests functions: * gui_bar_item_search