diff options
-rw-r--r-- | libdwfl/ChangeLog | 5 | ||||
-rw-r--r-- | libdwfl/derelocate.c | 37 |
2 files changed, 33 insertions, 9 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 47f3854a..83a26189 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,8 @@ +2015-05-18 Mark Wielaard <mjw@redhat.com> + + * derelocate.c (cache_sections): Allocate temporary newrefs and + sortrefs with malloc, not alloca. Always free them on return. + 2015-05-07 Mark Wielaard <mjw@redhat.com> * cu.c (intern_cu): Check for EOF and check cuoff points to a real diff --git a/libdwfl/derelocate.c b/libdwfl/derelocate.c index da679089..2889fe41 100644 --- a/libdwfl/derelocate.c +++ b/libdwfl/derelocate.c @@ -1,5 +1,5 @@ /* Recover relocatibility for addresses computed from debug information. - Copyright (C) 2005-2010, 2013 Red Hat, Inc. + Copyright (C) 2005-2010, 2013, 2015 Red Hat, Inc. This file is part of elfutils. This file is free software; you can redistribute it and/or modify @@ -80,7 +80,8 @@ cache_sections (Dwfl_Module *mod) { elf_error: __libdwfl_seterrno (DWFL_E_LIBELF); - return -1; + nrefs = -1; + goto free_refs; } bool check_reloc_sections = false; @@ -112,7 +113,15 @@ cache_sections (Dwfl_Module *mod) if (unlikely (name == NULL)) goto elf_error; - struct secref *newref = alloca (sizeof *newref); + struct secref *newref = malloc (sizeof *newref); + if (unlikely (newref == NULL)) + { + nomem: + __libdwfl_seterrno (DWFL_E_NOMEM); + nrefs = -1; + goto free_refs; + } + newref->scn = scn; newref->relocs = NULL; newref->name = name; @@ -147,13 +156,13 @@ cache_sections (Dwfl_Module *mod) } mod->reloc_info = malloc (offsetof (struct dwfl_relocation, refs[nrefs])); - if (mod->reloc_info == NULL) - { - __libdwfl_seterrno (DWFL_E_NOMEM); - return -1; - } + if (unlikely (mod->reloc_info == NULL)) + goto nomem; + + struct secref **sortrefs = malloc (nrefs * sizeof sortrefs[0]); + if (unlikely (sortrefs == NULL)) + goto nomem; - struct secref **sortrefs = alloca (nrefs * sizeof sortrefs[0]); for (size_t i = nrefs; i-- > 0; refs = refs->next) sortrefs[i] = refs; assert (refs == NULL); @@ -170,6 +179,8 @@ cache_sections (Dwfl_Module *mod) mod->reloc_info->refs[i].end = sortrefs[i]->end; } + free (sortrefs); + if (unlikely (check_reloc_sections)) { /* There was a reloc section that preceded its target section. @@ -199,6 +210,14 @@ cache_sections (Dwfl_Module *mod) } } +free_refs: + while (refs != NULL) + { + struct secref *ref = refs; + refs = ref->next; + free (ref); + } + return nrefs; } |