summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2015-12-02 15:44:10 +0100
committerMark Wielaard <mjw@redhat.com>2016-01-02 20:37:45 +0100
commit5c40529883a48e350b37e7de9ad285facdf84f6f (patch)
tree2f6f7a34aa3c210a6dabf097653e62643df25926
parente04da0e6bab6c6cca2d6e1657d18666f50d2ecfa (diff)
downloadelfutils-5c40529883a48e350b37e7de9ad285facdf84f6f.tar.gz
unstrip: Don't leak new section data.
When we copy elided sections some section data is newly allocated. Track those allocations so we can free them when done. Signed-off-by: Mark Wielaard <mjw@redhat.com>
-rw-r--r--src/ChangeLog10
-rw-r--r--src/unstrip.c39
2 files changed, 47 insertions, 2 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 27c638f9..be7768f6 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,13 @@
+2015-12-02 Mark Wielaard <mjw@redhat.com>
+
+ * unstrip.c (struct data_list): New.
+ (new_data_list): Likewise.
+ (record_new_data): Likewise.
+ (free_new_data): Likewise.
+ (adjust_relocs): Call record_new_data.
+ (add_new_section_symbols): Likewise.
+ (copy_elided_sections): Call free_new_data.
+
2015-12-01 Mark Wielaard <mjw@redhat.com>
* elfcmp.c (main): Close ebl1 and ebl2 backends.
diff --git a/src/unstrip.c b/src/unstrip.c
index bc8ed503..85e0a1da 100644
--- a/src/unstrip.c
+++ b/src/unstrip.c
@@ -311,6 +311,38 @@ make_directories (const char *path)
error (EXIT_FAILURE, errno, _("cannot create directory '%s'"), dir);
}
+/* Keep track of new section data we are creating, so we can free it
+ when done. */
+struct data_list
+{
+ void *data;
+ struct data_list *next;
+};
+
+struct data_list *new_data_list;
+
+static void
+record_new_data (void *data)
+{
+ struct data_list *next = new_data_list;
+ new_data_list = xmalloc (sizeof (struct data_list));
+ new_data_list->data = data;
+ new_data_list->next = next;
+}
+
+static void
+free_new_data (void)
+{
+ struct data_list *list = new_data_list;
+ while (list != NULL)
+ {
+ struct data_list *next = list->next;
+ free (list->data);
+ free (list);
+ list = next;
+ }
+ new_data_list = NULL;
+}
/* The binutils linker leaves gratuitous section symbols in .symtab
that strip has to remove. Older linkers likewise include a
@@ -472,6 +504,7 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
if (old_chain[i] != STN_UNDEF) \
new_chain[map[i - 1]] = map[old_chain[i] - 1]; \
\
+ record_new_data (new_hash); \
data->d_buf = new_hash; \
data->d_size = nent * sizeof new_hash[0]; \
}
@@ -514,6 +547,7 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
ELF_CHECK (v != NULL, _("cannot get symbol version: %s"));
}
+ record_new_data (versym);
data->d_buf = versym;
data->d_size = nent * shdr->sh_entsize;
elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY);
@@ -571,6 +605,7 @@ add_new_section_symbols (Elf_Scn *old_symscn, size_t old_shnum,
symdata->d_size = shdr->sh_size;
symdata->d_buf = xmalloc (symdata->d_size);
+ record_new_data (symdata->d_buf);
/* Copy the existing section symbols. */
Elf_Data *old_symdata = elf_getdata (old_symscn, NULL);
@@ -1762,6 +1797,7 @@ more sections in stripped file than debug file -- arguments reversed?"));
shdr->sh_size = symdata->d_size = (1 + nsym) * shdr->sh_entsize;
symdata->d_buf = xmalloc (symdata->d_size);
+ record_new_data (symdata->d_buf);
GElf_Sym sym;
memset (&sym, 0, sizeof sym);
@@ -1927,13 +1963,12 @@ more sections in stripped file than debug file -- arguments reversed?"));
free (strtab_data->d_buf);
}
- if (symdata != NULL)
- free (symdata->d_buf);
if (symstrtab != NULL)
{
ebl_strtabfree (symstrtab);
free (symstrdata->d_buf);
}
+ free_new_data ();
}
/* Process one pair of files, already opened. */