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.  */