]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
dwarf_begin_elf.c: Fix lock resource leak
authorAaron Merey <amerey@redhat.com>
Tue, 24 Feb 2026 21:08:07 +0000 (16:08 -0500)
committerAaron Merey <amerey@redhat.com>
Wed, 25 Feb 2026 13:11:38 +0000 (08:11 -0500)
dwarf_begin_elf might free memory for a struct Dwarf after its rwlock and
mutex fields have been initialized without calling the corresponding
destroy functions to release the lock resources.

Fix this by moving lock inits to the end of the valid_p function, after
the struct Dwarf being intialized has passed all error checking.

Signed-off-by: Aaron Merey <amerey@redhat.com>
libdw/dwarf_begin_elf.c

index f5cabde0711135a9e1cca529a8a12716ca8250ee..dd30f79b34a40e2c5a831fef768c86b9774c52f9 100644 (file)
@@ -358,12 +358,6 @@ valid_p (Dwarf *result)
          result->fake_loc_cu->offset_size = 4;
          result->fake_loc_cu->version = 4;
          result->fake_loc_cu->split = NULL;
-         eu_search_tree_init (&result->fake_loc_cu->locs_tree);
-         rwlock_init (result->fake_loc_cu->split_lock);
-         mutex_init (result->fake_loc_cu->abbrev_lock);
-         mutex_init (result->fake_loc_cu->src_lock);
-         mutex_init (result->fake_loc_cu->str_off_base_lock);
-         mutex_init (result->fake_loc_cu->intern_lock);
        }
     }
 
@@ -391,12 +385,6 @@ valid_p (Dwarf *result)
          result->fake_loclists_cu->offset_size = 4;
          result->fake_loclists_cu->version = 5;
          result->fake_loclists_cu->split = NULL;
-         eu_search_tree_init (&result->fake_loclists_cu->locs_tree);
-         rwlock_init (result->fake_loclists_cu->split_lock);
-         mutex_init (result->fake_loclists_cu->abbrev_lock);
-         mutex_init (result->fake_loclists_cu->src_lock);
-         mutex_init (result->fake_loclists_cu->str_off_base_lock);
-         mutex_init (result->fake_loclists_cu->intern_lock);
        }
     }
 
@@ -429,19 +417,62 @@ valid_p (Dwarf *result)
          result->fake_addr_cu->offset_size = 4;
          result->fake_addr_cu->version = 5;
          result->fake_addr_cu->split = NULL;
-         eu_search_tree_init (&result->fake_addr_cu->locs_tree);
-         rwlock_init (result->fake_addr_cu->split_lock);
-         mutex_init (result->fake_addr_cu->abbrev_lock);
-         mutex_init (result->fake_addr_cu->src_lock);
-         mutex_init (result->fake_addr_cu->str_off_base_lock);
-         mutex_init (result->fake_addr_cu->intern_lock);
        }
     }
 
   if (result != NULL)
     {
+      if (pthread_rwlock_init(&result->mem_rwl, NULL) != 0)
+       {
+         free (result->fake_loc_cu);
+         free (result->fake_loclists_cu);
+         free (result->fake_addr_cu);
+         free (result);
+         __libdw_seterrno (DWARF_E_NOMEM); /* no memory.  */
+         return NULL;
+       }
+
       result->elfpath = __libdw_elfpath (result->elf->fildes);
       __libdw_set_debugdir(result);
+
+      /* Initialize locks and search_trees.  */
+      mutex_init (result->dwarf_lock);
+      mutex_init (result->macro_lock);
+      eu_search_tree_init (&result->cu_tree);
+      eu_search_tree_init (&result->tu_tree);
+      eu_search_tree_init (&result->split_tree);
+      eu_search_tree_init (&result->macro_ops_tree);
+      eu_search_tree_init (&result->files_lines_tree);
+
+      if (result->fake_loc_cu != NULL)
+       {
+         eu_search_tree_init (&result->fake_loc_cu->locs_tree);
+         rwlock_init (result->fake_loc_cu->split_lock);
+         mutex_init (result->fake_loc_cu->abbrev_lock);
+         mutex_init (result->fake_loc_cu->src_lock);
+         mutex_init (result->fake_loc_cu->str_off_base_lock);
+         mutex_init (result->fake_loc_cu->intern_lock);
+       }
+
+      if (result->fake_loclists_cu != NULL)
+       {
+         eu_search_tree_init (&result->fake_loclists_cu->locs_tree);
+         rwlock_init (result->fake_loclists_cu->split_lock);
+         mutex_init (result->fake_loclists_cu->abbrev_lock);
+         mutex_init (result->fake_loclists_cu->src_lock);
+         mutex_init (result->fake_loclists_cu->str_off_base_lock);
+         mutex_init (result->fake_loclists_cu->intern_lock);
+       }
+
+      if (result->fake_addr_cu != NULL)
+       {
+         eu_search_tree_init (&result->fake_addr_cu->locs_tree);
+         rwlock_init (result->fake_addr_cu->split_lock);
+         mutex_init (result->fake_addr_cu->abbrev_lock);
+         mutex_init (result->fake_addr_cu->src_lock);
+         mutex_init (result->fake_addr_cu->str_off_base_lock);
+         mutex_init (result->fake_addr_cu->intern_lock);
+       }
     }
 
   return result;
@@ -588,19 +619,6 @@ dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp)
      actual allocation.  */
   result->mem_default_size = mem_default_size;
   result->oom_handler = __libdw_oom;
-  if (pthread_rwlock_init(&result->mem_rwl, NULL) != 0)
-    {
-      free (result);
-      __libdw_seterrno (DWARF_E_NOMEM); /* no memory.  */
-      return NULL;
-    }
-  mutex_init (result->dwarf_lock);
-  mutex_init (result->macro_lock);
-  eu_search_tree_init (&result->cu_tree);
-  eu_search_tree_init (&result->tu_tree);
-  eu_search_tree_init (&result->split_tree);
-  eu_search_tree_init (&result->macro_ops_tree);
-  eu_search_tree_init (&result->files_lines_tree);
 
   result->mem_stacks = 0;
   result->mem_tails = NULL;