summaryrefslogtreecommitdiffstats
path: root/src/unstrip.c
diff options
context:
space:
mode:
authorChih-Hung Hsieh <[email protected]>2015-10-06 15:53:15 -0700
committerMark Wielaard <[email protected]>2015-10-07 22:44:41 +0200
commit7eff36d5daa6ebca5e6399638a7643af105ae5b0 (patch)
tree7bfd9c4a93f88135b9f42337d827948aa6b63cdb /src/unstrip.c
parentdaee4714ee3761e2d92f764a724e83875a79a3f0 (diff)
Do without union of variable length arrays.
Prepare to compile with clang. A union like { T32 a32[n]; T64 a64[n]; } u; is expanded to size_t nbytes = n * MAX(sizeof(T32), sizeof(T64)); void *data = malloc(nbytes); T32 (*a32)[n] = data; T64 (*a64)[n] = data; Signed-off-by: Chih-Hung Hsieh <[email protected]>
Diffstat (limited to 'src/unstrip.c')
-rw-r--r--src/unstrip.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/src/unstrip.c b/src/unstrip.c
index d193708a..2a35deca 100644
--- a/src/unstrip.c
+++ b/src/unstrip.c
@@ -54,6 +54,10 @@
# define _(str) gettext (str)
#endif
+#ifndef MAX
+# define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
/* Name and version of program. */
static void print_version (FILE *stream, struct argp_state *state);
ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
@@ -1013,13 +1017,17 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
error (EXIT_FAILURE, 0, _("invalid contents in '%s' section"),
".gnu.prelink_undo");
- union
- {
- Elf32_Shdr s32[shnum - 1];
- Elf64_Shdr s64[shnum - 1];
- } shdr;
- dst.d_buf = &shdr;
- dst.d_size = sizeof shdr;
+ if (unlikely ((shnum - 1) >
+ SIZE_MAX / MAX (sizeof (Elf32_Shdr), sizeof (Elf64_Shdr))))
+ error (EXIT_FAILURE, 0, _("overflow with shnum = %zu in '%s' section"),
+ (size_t) shnum, ".gnu.prelink_undo");
+ const size_t shdr_bytes =
+ (shnum - 1) * MAX (sizeof (Elf32_Shdr), sizeof (Elf64_Shdr));
+ void *shdr = xmalloc (shdr_bytes);
+ Elf32_Shdr (*s32)[shnum - 1] = shdr;
+ Elf64_Shdr (*s64)[shnum - 1] = shdr;
+ dst.d_buf = shdr;
+ dst.d_size = shdr_bytes;
ELF_CHECK (gelf_xlatetom (main, &dst, &src,
main_ehdr->e_ident[EI_DATA]) != NULL,
_("cannot read '.gnu.prelink_undo' section: %s"));
@@ -1030,7 +1038,7 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
struct section *sec = &undo_sections[undo_nalloc];
if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
{
-#define COPY(field) sec->shdr.field = shdr.s32[i].field
+#define COPY(field) sec->shdr.field = (*s32)[i].field
COPY (sh_name);
COPY (sh_type);
COPY (sh_flags);
@@ -1044,7 +1052,7 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
#undef COPY
}
else
- sec->shdr = shdr.s64[i];
+ sec->shdr = (*s64)[i];
if (sec->shdr.sh_flags & SHF_ALLOC)
{
sec->shdr.sh_addr += bias;
@@ -1057,6 +1065,7 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
}
qsort (undo_sections, undo_nalloc,
sizeof undo_sections[0], compare_sections_nonrel);
+ free (shdr);
}
bool fail = false;