diff options
| author | Chih-Hung Hsieh <[email protected]> | 2015-10-06 15:53:15 -0700 |
|---|---|---|
| committer | Mark Wielaard <[email protected]> | 2015-10-07 22:44:41 +0200 |
| commit | 7eff36d5daa6ebca5e6399638a7643af105ae5b0 (patch) | |
| tree | 7bfd9c4a93f88135b9f42337d827948aa6b63cdb /src/unstrip.c | |
| parent | daee4714ee3761e2d92f764a724e83875a79a3f0 (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.c | 27 |
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; |
