summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlbrecht Schlosser <albrechts.fltk@online.de>2023-12-23 19:48:58 +0100
committerAlbrecht Schlosser <albrechts.fltk@online.de>2023-12-23 20:05:48 +0100
commit016c36c917de79383fb2d81c267faa0829147bdf (patch)
tree9de931553e58e885d741dfab901c2b5dc7fb2d8e /src
parentf59702e290be9ededeeae9f0e78b422cf359de3f (diff)
Fix memory free() mismatch (#875)
This issue was revealed during testing for GitHub Issue #875. "ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed", reported by examples/howto-menu-with-images.cxx if the window object was released at the end of the program, causing Fl_Menu_::clear() to be called. The issue was caused by casting all supported label types to 'const char *' which are stored in Fl_Menu_Item::text and then trying to free() all text strings in Fl_Menu_::clear() under certain conditions. Now images and Fl_Multi_Label's are no longer (tried to be) free'd.
Diffstat (limited to 'src')
-rw-r--r--src/Fl_Menu_.cxx29
1 files changed, 27 insertions, 2 deletions
diff --git a/src/Fl_Menu_.cxx b/src/Fl_Menu_.cxx
index 0d82d92dc..73998ba7e 100644
--- a/src/Fl_Menu_.cxx
+++ b/src/Fl_Menu_.cxx
@@ -500,8 +500,33 @@ Fl_Menu_* fl_menu_array_owner = 0;
*/
void Fl_Menu_::clear() {
if (alloc) {
- if (alloc>1) for (int i = size(); i--;)
- if (menu_[i].text) free((void*)menu_[i].text);
+
+ if (alloc > 1) {
+
+ // See GitHub issue #875: we can't release "everything"
+ // for several reasons. Maybe we can do better if we create
+ // a new menu system based on Fl_Widget in 1.5.0 or later.
+
+ // Fl_Image's and Fl_Multi_Label's and their linked objects
+ // can't be released automatically. However, we must take care
+ // not to free() images or Fl_Multi_Label's because they can
+ // either be static or are allocated by operator new.
+
+ for (int i = size(); i--;) {
+ if (!menu_[i].text)
+ continue;
+ switch(menu_[i].labeltype_) {
+ case _FL_IMAGE_LABEL:
+ break;
+ case _FL_MULTI_LABEL:
+ break;
+ default:
+ free((void*)menu_[i].text);
+ break;
+ }
+ }
+ }
+
if (this == fl_menu_array_owner)
fl_menu_array_owner = 0;
else