Although it isn't supposed to happen there could be FDEs that cover the same address range. Don't leak such FDEs and use an existing FDE for consistency. Signed-off-by: Mark Wielaard --- libdw/ChangeLog | 4 ++++ libdw/fde.c | 11 ++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 10df13b..f8b4793 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,7 @@ +2015-12-02 Mark Wielaard + + * fde.c (intern_fde): Don't leak duplicate FDEs. + 2015-12-01 Mark Wielaard * fde.c (intern_fde): Don't intern an fde that doesn't cover a diff --git a/libdw/fde.c b/libdw/fde.c index 2a59d3e..f5f6fbe 100644 --- a/libdw/fde.c +++ b/libdw/fde.c @@ -119,12 +119,21 @@ intern_fde (Dwarf_CFI *cache, const Dwarf_FDE *entry) fde->instructions += cie->fde_augmentation_data_size; /* Add the new entry to the search tree. */ - if (tsearch (fde, &cache->fde_tree, &compare_fde) == NULL) + struct dwarf_fde **tres = tsearch (fde, &cache->fde_tree, &compare_fde); + if (tres == NULL) { free (fde); __libdw_seterrno (DWARF_E_NOMEM); return NULL; } + else if (*tres != fde) + { + /* There is already an FDE in the cache that covers the same + address range. That is odd. Ignore this FDE. And just use + the one in the cache for consistency. */ + free (fde); + return *tres; + } return fde; } -- 2.5.0