readelf: Fix overlarge memory allocation when reading a binary with an excessive...
[binutils-gdb.git] / binutils / readelf.c
index 6ede2399fc574af9949e80b34438eb443d2fd49e..b573921c13819133ca15a056dbbc6aaf24c28049 100644 (file)
 #include "elf/v850.h"
 #include "elf/vax.h"
 #include "elf/visium.h"
+#include "elf/wasm32.h"
 #include "elf/x86-64.h"
 #include "elf/xc16x.h"
 #include "elf/xgate.h"
@@ -809,6 +810,7 @@ guess_is_rela (unsigned int e_machine)
     case EM_XTENSA_OLD:
     case EM_MICROBLAZE:
     case EM_MICROBLAZE_OLD:
+    case EM_WEBASSEMBLY:
       return TRUE;
 
     case EM_68HC05:
@@ -1498,6 +1500,10 @@ dump_relocations (FILE * file,
          rtype = elf_tilepro_reloc_type (type);
          break;
 
+       case EM_WEBASSEMBLY:
+         rtype = elf_wasm32_reloc_type (type);
+         break;
+
        case EM_XGATE:
          rtype = elf_xgate_reloc_type (type);
          break;
@@ -4788,9 +4794,19 @@ get_program_headers (FILE * file)
   if (program_headers != NULL)
     return TRUE;
 
-  phdrs = (Elf_Internal_Phdr *) cmalloc (elf_header.e_phnum,
-                                         sizeof (Elf_Internal_Phdr));
+  /* Be kind to memory checkers by looking for
+     e_phnum values which we know must be invalid.  */
+  if (elf_header.e_phnum
+      * (is_32bit_elf ? sizeof (Elf32_External_Phdr) : sizeof (Elf64_External_Phdr))
+      >= current_file_size)
+    {
+      error (_("Too many program headers - %#x - the file is not that big\n"),
+            elf_header.e_phnum);
+      return FALSE;
+    }
 
+  phdrs = (Elf_Internal_Phdr *) cmalloc (elf_header.e_phnum,
+                                        sizeof (Elf_Internal_Phdr));
   if (phdrs == NULL)
     {
       error (_("Out of memory reading %u program headers\n"),
@@ -8047,9 +8063,9 @@ get_unwind_section_word (struct arm_unw_aux_info *  aux,
     return FALSE;
 
   /* If the offset is invalid then fail.  */
-  if (word_offset > (sec->sh_size - 4)
-      /* PR 18879 */
-      || (sec->sh_size < 5 && word_offset >= sec->sh_size)
+  if (/* PR 21343 *//* PR 18879 */
+      sec->sh_size < 4
+      || word_offset > (sec->sh_size - 4)
       || ((bfd_signed_vma) word_offset) < 0)
     return FALSE;
 
@@ -12091,6 +12107,8 @@ is_32bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 1; /* R_VAX_32.  */
     case EM_VISIUM:
       return reloc_type == 3;  /* R_VISIUM_32. */
+    case EM_WEBASSEMBLY:
+      return reloc_type == 1;  /* R_WASM32_32.  */
     case EM_X86_64:
     case EM_L1OM:
     case EM_K1OM:
@@ -12396,6 +12414,7 @@ is_none_reloc (unsigned int reloc_type)
     case EM_TI_C6000:/* R_C6000_NONE.  */
     case EM_X86_64:  /* R_X86_64_NONE.  */
     case EM_XC16X:
+    case EM_WEBASSEMBLY: /* R_WASM32_NONE.  */
       return reloc_type == 0;
 
     case EM_AARCH64:
@@ -15455,14 +15474,25 @@ process_mips_specific (FILE * file)
       printf (_(" Lazy resolver\n"));
       if (ent == (bfd_vma) -1)
        goto got_print_fail;
-      if (data
-         && (byte_get (data + ent - pltgot, addr_size)
-             >> (addr_size * 8 - 1)) != 0)
-       {
-         ent = print_mips_got_entry (data, pltgot, ent, data_end);
-         printf (_(" Module pointer (GNU extension)\n"));
-         if (ent == (bfd_vma) -1)
-           goto got_print_fail;
+
+      if (data)
+       {
+         /* PR 21344 */
+         if (data + ent - pltgot > data_end - addr_size)
+           {
+             error (_("Invalid got entry - %#lx - overflows GOT table\n"),
+                    (long) ent);
+             goto got_print_fail;
+           }
+         
+         if (byte_get (data + ent - pltgot, addr_size)
+             >> (addr_size * 8 - 1) != 0)
+           {
+             ent = print_mips_got_entry (data, pltgot, ent, data_end);
+             printf (_(" Module pointer (GNU extension)\n"));
+             if (ent == (bfd_vma) -1)
+               goto got_print_fail;
+           }
        }
       printf ("\n");