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 <chh@google.com>
diff --git a/libdwfl/elf-from-memory.c b/libdwfl/elf-from-memory.c
index ed8f6e9..5be21bb 100644
--- a/libdwfl/elf-from-memory.c
+++ b/libdwfl/elf-from-memory.c
@@ -38,6 +38,10 @@
#include <stdlib.h>
#include <string.h>
+#ifndef MAX
+# define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
/* Reconstruct an ELF file by reading the segments out of remote memory
based on the ELF file header at EHDR_VMA and the ELF program headers it
points to. If not null, *LOADBASEP is filled in with the difference
@@ -191,22 +195,25 @@
xlatefrom.d_buf = buffer;
}
- typedef union
- {
- Elf32_Phdr p32[phnum];
- Elf64_Phdr p64[phnum];
- } phdrsn;
-
- phdrsp = malloc (sizeof (phdrsn));
+ if (unlikely (phnum >
+ SIZE_MAX / MAX (sizeof (Elf32_Phdr), sizeof (Elf64_Phdr))))
+ {
+ free (buffer);
+ goto no_memory;
+ }
+ const size_t phdrsp_bytes =
+ phnum * MAX (sizeof (Elf32_Phdr), sizeof (Elf64_Phdr));
+ phdrsp = malloc (phdrsp_bytes);
+ Elf32_Phdr (*p32)[phnum] = phdrsp;
+ Elf64_Phdr (*p64)[phnum] = phdrsp;
if (unlikely (phdrsp == NULL))
{
free (buffer);
goto no_memory;
}
- phdrsn *phdrs = (phdrsn *) phdrsp;
- xlateto.d_buf = phdrs;
- xlateto.d_size = sizeof (phdrsn);
+ xlateto.d_buf = phdrsp;
+ xlateto.d_size = phdrsp_bytes;
/* Scan for PT_LOAD segments to find the total size of the file image. */
size_t contents_size = 0;
@@ -249,9 +256,9 @@
ehdr.e32.e_ident[EI_DATA]) == NULL)
goto libelf_error;
for (uint_fast16_t i = 0; i < phnum; ++i)
- if (phdrs->p32[i].p_type == PT_LOAD)
- if (handle_segment (phdrs->p32[i].p_vaddr, phdrs->p32[i].p_offset,
- phdrs->p32[i].p_filesz, phdrs->p32[i].p_memsz))
+ if ((*p32)[i].p_type == PT_LOAD)
+ if (handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
+ (*p32)[i].p_filesz, (*p32)[i].p_memsz))
goto bad_elf;
break;
@@ -260,9 +267,9 @@
ehdr.e64.e_ident[EI_DATA]) == NULL)
goto libelf_error;
for (uint_fast16_t i = 0; i < phnum; ++i)
- if (phdrs->p64[i].p_type == PT_LOAD)
- if (handle_segment (phdrs->p64[i].p_vaddr, phdrs->p64[i].p_offset,
- phdrs->p64[i].p_filesz, phdrs->p64[i].p_memsz))
+ if ((*p64)[i].p_type == PT_LOAD)
+ if (handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
+ (*p64)[i].p_filesz, (*p64)[i].p_memsz))
goto bad_elf;
break;
@@ -315,9 +322,9 @@
case ELFCLASS32:
for (uint_fast16_t i = 0; i < phnum; ++i)
- if (phdrs->p32[i].p_type == PT_LOAD)
- if (handle_segment (phdrs->p32[i].p_vaddr, phdrs->p32[i].p_offset,
- phdrs->p32[i].p_filesz))
+ if ((*p32)[i].p_type == PT_LOAD)
+ if (handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
+ (*p32)[i].p_filesz))
goto read_error;
/* If the segments visible in memory didn't include the section
@@ -342,9 +349,9 @@
case ELFCLASS64:
for (uint_fast16_t i = 0; i < phnum; ++i)
- if (phdrs->p64[i].p_type == PT_LOAD)
- if (handle_segment (phdrs->p64[i].p_vaddr, phdrs->p64[i].p_offset,
- phdrs->p64[i].p_filesz))
+ if ((*p64)[i].p_type == PT_LOAD)
+ if (handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
+ (*p64)[i].p_filesz))
goto read_error;
/* If the segments visible in memory didn't include the section
@@ -373,7 +380,7 @@
}
free (phdrsp);
- phdrs = phdrsp = NULL;
+ phdrsp = NULL;
/* Now we have the image. Open libelf on it. */