summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2008-12-11 02:09:28 -0800
committerRoland McGrath <roland@redhat.com>2008-12-11 02:09:28 -0800
commitb28a894209451b93ba830f56e40871e44e9c7c28 (patch)
tree54e89f81fb9a783d4b3f382136c60d100c01ac0b
parentd353328036180fc028fd367e5fd49e69511b4436 (diff)
Fixes RHBZ#465878: eu-readelf crash on empty archive
-rw-r--r--libdwfl/ChangeLog7
-rw-r--r--libdwfl/offline.c17
2 files changed, 19 insertions, 5 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 41ff69bc..4f03855f 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,10 @@
+2008-12-11 Roland McGrath <roland@redhat.com>
+
+ * offline.c (process_archive): Don't call elf_end and close if
+ returning NULL. Check first elf_begin call and set error code
+ specially for empty archive.
+ Fixes RHBZ#465878.
+
2008-12-02 Roland McGrath <roland@redhat.com>
* dwfl_getmodules.c (dwfl_getmodules): Typo fix in last change.
diff --git a/libdwfl/offline.c b/libdwfl/offline.c
index ff7b793a..b3a95dd9 100644
--- a/libdwfl/offline.c
+++ b/libdwfl/offline.c
@@ -1,5 +1,5 @@
/* Recover relocatibility for addresses computed from debug information.
- Copyright (C) 2005, 2006, 2007 Red Hat, Inc.
+ Copyright (C) 2005, 2006, 2007, 2008 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -259,16 +259,23 @@ process_archive (Dwfl *dwfl, const char *name, const char *file_name, int fd,
{
Dwfl_Module *mod = NULL;
+ Elf *member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive);
+ if (unlikely (member == NULL)) /* Empty archive. */
+ {
+ __libdwfl_seterrno (DWFL_E_BADELF);
+ return NULL;
+ }
+
while (process_archive_member (dwfl, name, file_name, predicate,
- fd, elf_begin (fd, ELF_C_READ_MMAP_PRIVATE,
- archive), &mod) != ELF_C_NULL)
- ;
+ fd, member, &mod) != ELF_C_NULL)
+ member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive);
/* We can drop the archive Elf handle even if we're still using members
in live modules. When the last module's elf_end on a member returns
zero, that module will close FD. If no modules survived the predicate,
we are all done with the file right here. */
- if (elf_end (archive) == 0)
+ if (mod != NULL /* If no modules, caller will clean up. */
+ && elf_end (archive) == 0)
close (fd);
return mod;