summaryrefslogtreecommitdiffstats
path: root/src
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
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')
-rw-r--r--src/ChangeLog8
-rw-r--r--src/readelf.c26
-rw-r--r--src/unstrip.c27
3 files changed, 43 insertions, 18 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index daa76cf2..e6744017 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,11 @@
+2015-10-05 Chih-Hung Hsieh <[email protected]>
+
+ * unstrip.c (find_alloc_sections_prelink): Do not allocate
+ on stack union types with variable length arrays; use xmalloc
+ for such dynamic sized objects.
+ * readelf.c (handle_core_item): Likewise, but use alloca
+ for small variable size data object and add assert(count < 128).
+
2015-10-05 Josh Stone <[email protected]>
* Makefile.am (libld_elf_i386.so): Add AM_V_CCLD silencer.
diff --git a/src/readelf.c b/src/readelf.c
index 33274f35..fe7bc392 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -8370,6 +8370,9 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
unsigned int colno, size_t *repeated_size)
{
uint_fast16_t count = item->count ?: 1;
+ /* Ebl_Core_Item count is always a small number.
+ Make sure the backend didn't put in some large bogus value. */
+ assert (count < 128);
#define TYPES \
DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8); \
@@ -8379,11 +8382,16 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64); \
DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64)
-#define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name[count]
- union { TYPES; } value;
+#define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name
+ typedef union { TYPES; } value_t;
+ void *data = alloca (count * sizeof (value_t));
+#undef DO_TYPE
+
+#define DO_TYPE(NAME, Name, hex, dec) \
+ GElf_##Name *value_##Name __attribute__((unused)) = data
+ TYPES;
#undef DO_TYPE
- void *data = &value;
size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
size_t convsize = size;
if (repeated_size != NULL)
@@ -8414,7 +8422,7 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
#define DO_TYPE(NAME, Name, hex, dec) \
case ELF_T_##NAME: \
colno = print_core_item (colno, ',', WRAP_COLUMN, \
- 0, item->name, dec, value.Name[0]); \
+ 0, item->name, dec, value_##Name[0]); \
break
TYPES;
#undef DO_TYPE
@@ -8430,7 +8438,7 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
#define DO_TYPE(NAME, Name, hex, dec) \
case ELF_T_##NAME: \
colno = print_core_item (colno, ',', WRAP_COLUMN, \
- 0, item->name, hex, value.Name[0]); \
+ 0, item->name, hex, value_##Name[0]); \
break
TYPES;
#undef DO_TYPE
@@ -8520,8 +8528,8 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
{
#define DO_TYPE(NAME, Name, hex, dec) \
case ELF_T_##NAME: \
- sec = value.Name[0]; \
- usec = value.Name[1]; \
+ sec = value_##Name[0]; \
+ usec = value_##Name[1]; \
break
TYPES;
#undef DO_TYPE
@@ -8551,12 +8559,12 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
case 'c':
assert (count == 1);
colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
- "%c", value.Byte[0]);
+ "%c", value_Byte[0]);
break;
case 's':
colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
- "%.*s", (int) count, value.Byte);
+ "%.*s", (int) count, value_Byte);
break;
case '\n':
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;