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 <[email protected]> --- libdw/dwarf_begin_elf.c | 80 +++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 31 deletions(-) diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c index f5cabde0..dd30f79b 100644 --- a/libdw/dwarf_begin_elf.c +++ b/libdw/dwarf_begin_elf.c @@ -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; -- 2.53.0
