PR28403, null pointer dereference in disassemble_bytes
authorAlan Modra <amodra@gmail.com>
Tue, 5 Oct 2021 23:47:29 +0000 (10:17 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 6 Oct 2021 00:54:29 +0000 (11:24 +1030)
Indexing of symbol and howto arrays wasn't checked in aout targets.

PR 28403
* aout-ns32k.c (MY (reloc_howto)): Sanity check howto_table index.
Make r_index unsigned.
(MY_swap_std_reloc_in): Make r_index unsigned.
* aoutx.h (MOVE_ADDRESS): Sanity check symbol r_index.
(aout_link_input_section_std): Make r_index unsigned.
(aout_link_input_section_ext): Likewise.
* i386lynx.c (MOVE_ADDRESS): Sanity check symbol r_index.
(swap_ext_reloc_in, swap_std_reloc_in): Make r_index unsigned.
* pdp11.c (MOVE_ADDRESS): Sanity check symbol r_index.

bfd/aout-ns32k.c
bfd/aoutx.h
bfd/i386lynx.c
bfd/pdp11.c

index 83fde67cc26932fd4982943b9d8dd7241ee663d1..eb721b256d1bc72439bbb87bba5c857cea219deb 100644 (file)
@@ -143,12 +143,12 @@ reloc_howto_type MY (howto_table)[] =
 static reloc_howto_type *
 MY (reloc_howto) (bfd *abfd ATTRIBUTE_UNUSED,
                  struct reloc_std_external *rel,
-                 int *r_index,
+                 unsigned int *r_index,
                  int *r_extern,
                  int *r_pcrel)
 {
   unsigned int r_length;
-  int r_ns32k_type;
+  unsigned int r_ns32k_type;
 
   *r_index =  ((rel->r_index[2] << 16)
               | (rel->r_index[1] << 8)
@@ -159,6 +159,8 @@ MY (reloc_howto) (bfd *abfd ATTRIBUTE_UNUSED,
                >> RELOC_STD_BITS_LENGTH_SH_LITTLE);
   r_ns32k_type  =  ((rel->r_type[0] & RELOC_STD_BITS_NS32K_TYPE_LITTLE)
                    >> RELOC_STD_BITS_NS32K_TYPE_SH_LITTLE);
+  if (r_length > 2 || r_ns32k_type > 2)
+    return NULL;
   return (MY (howto_table) + r_length + 3 * (*r_pcrel) + 6 * r_ns32k_type);
 }
 
@@ -271,7 +273,7 @@ MY_swap_std_reloc_in (bfd *abfd,
                      asymbol **symbols,
                      bfd_size_type symcount ATTRIBUTE_UNUSED)
 {
-  int r_index;
+  unsigned int r_index;
   int r_extern;
   int r_pcrel;
   struct aoutdata  *su = &(abfd->tdata.aout_data->a);
index 17560bd8f54a55d7cf8bd1c09019c60d969e648b..ea09646f2b37e91e29e8cc418e29b1e404e72e1f 100644 (file)
@@ -2130,7 +2130,8 @@ NAME (aout, swap_ext_reloc_out) (bfd *abfd,
   if (r_extern)                                                                \
     {                                                                  \
       /* Undefined symbol.  */                                         \
-      cache_ptr->sym_ptr_ptr = symbols + r_index;                      \
+      if (r_index < bfd_get_symcount (abfd))                           \
+       cache_ptr->sym_ptr_ptr = symbols + r_index;                     \
       cache_ptr->addend = ad;                                          \
     }                                                                  \
    else                                                                        \
@@ -4021,7 +4022,7 @@ aout_link_input_section_std (struct aout_final_link_info *flaginfo,
   for (; rel < rel_end; rel++)
     {
       bfd_vma r_addr;
-      int r_index;
+      unsigned int r_index;
       int r_extern;
       int r_pcrel;
       int r_baserel = 0;
@@ -4133,7 +4134,7 @@ aout_link_input_section_std (struct aout_final_link_info *flaginfo,
                     map.  */
                  r_index = symbol_map[r_index];
 
-                 if (r_index == -1)
+                 if (r_index == -1u)
                    {
                      if (h != NULL)
                        {
@@ -4369,7 +4370,7 @@ aout_link_input_section_ext (struct aout_final_link_info *flaginfo,
   for (; rel < rel_end; rel++)
     {
       bfd_vma r_addr;
-      int r_index;
+      unsigned int r_index;
       int r_extern;
       unsigned int r_type;
       bfd_vma r_addend;
@@ -4469,7 +4470,7 @@ aout_link_input_section_ext (struct aout_final_link_info *flaginfo,
                     map.  */
                  r_index = symbol_map[r_index];
 
-                 if (r_index == -1)
+                 if (r_index == -1u)
                    {
                      if (h != NULL)
                        {
index c477e661c81d542e8b53de511cd6af87616fdb70..932ce1741e2f745b47ab11e5559ad1f5d5ed81da 100644 (file)
@@ -282,38 +282,40 @@ NAME(lynx,swap_ext_reloc_out) (bfd *abfd,
 #define MOVE_ADDRESS(ad)                                               \
   if (r_extern)                                                                \
     {                                                                  \
-   /* undefined symbol */                                              \
-     cache_ptr->sym_ptr_ptr = symbols + r_index;                       \
-     cache_ptr->addend = ad;                                           \
+      /* undefined symbol */                                           \
+      if (r_index < bfd_get_symcount (abfd))                           \
+       cache_ptr->sym_ptr_ptr = symbols + r_index;                     \
+      cache_ptr->addend = ad;                                          \
     }                                                                  \
   else                                                                 \
     {                                                                  \
-    /* defined, section relative. replace symbol with pointer to       \
-       symbol which points to section  */                              \
-    switch (r_index) {                                                 \
-    case N_TEXT:                                                       \
-    case N_TEXT | N_EXT:                                               \
-      cache_ptr->sym_ptr_ptr  = obj_textsec(abfd)->symbol_ptr_ptr;     \
-      cache_ptr->addend = ad  - su->textsec->vma;                      \
-      break;                                                           \
-    case N_DATA:                                                       \
-    case N_DATA | N_EXT:                                               \
-      cache_ptr->sym_ptr_ptr  = obj_datasec(abfd)->symbol_ptr_ptr;     \
-      cache_ptr->addend = ad - su->datasec->vma;                       \
-      break;                                                           \
-    case N_BSS:                                                                \
-    case N_BSS | N_EXT:                                                        \
-      cache_ptr->sym_ptr_ptr  = obj_bsssec(abfd)->symbol_ptr_ptr;      \
-      cache_ptr->addend = ad - su->bsssec->vma;                                \
-      break;                                                           \
-    default:                                                           \
-    case N_ABS:                                                                \
-    case N_ABS | N_EXT:                                                        \
-     cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;     \
-      cache_ptr->addend = ad;                                          \
-      break;                                                           \
+      /* defined, section relative. replace symbol with pointer to     \
+        symbol which points to section  */                             \
+      switch (r_index)                                                 \
+       {                                                               \
+       case N_TEXT:                                                    \
+       case N_TEXT | N_EXT:                                            \
+         cache_ptr->sym_ptr_ptr  = obj_textsec(abfd)->symbol_ptr_ptr;  \
+         cache_ptr->addend = ad  - su->textsec->vma;                   \
+         break;                                                        \
+       case N_DATA:                                                    \
+       case N_DATA | N_EXT:                                            \
+         cache_ptr->sym_ptr_ptr  = obj_datasec(abfd)->symbol_ptr_ptr;  \
+         cache_ptr->addend = ad - su->datasec->vma;                    \
+         break;                                                        \
+       case N_BSS:                                                     \
+       case N_BSS | N_EXT:                                             \
+         cache_ptr->sym_ptr_ptr  = obj_bsssec(abfd)->symbol_ptr_ptr;   \
+         cache_ptr->addend = ad - su->bsssec->vma;                     \
+         break;                                                        \
+       default:                                                        \
+       case N_ABS:                                                     \
+       case N_ABS | N_EXT:                                             \
+         cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
+         cache_ptr->addend = ad;                                       \
+         break;                                                        \
+       }                                                               \
     }                                                                  \
-  }                                                                    \
 
 static void
 NAME(lynx,swap_ext_reloc_in) (bfd *abfd,
@@ -322,7 +324,7 @@ NAME(lynx,swap_ext_reloc_in) (bfd *abfd,
                              asymbol **symbols,
                              bfd_size_type symcount ATTRIBUTE_UNUSED)
 {
-  int r_index;
+  unsigned int r_index;
   int r_extern;
   unsigned int r_type;
   struct aoutdata *su = &(abfd->tdata.aout_data->a);
@@ -345,7 +347,7 @@ NAME(lynx,swap_std_reloc_in) (bfd *abfd,
                              asymbol **symbols,
                              bfd_size_type symcount ATTRIBUTE_UNUSED)
 {
-  int r_index;
+  unsigned int r_index;
   int r_extern;
   unsigned int r_length;
   int r_pcrel;
index 2c9fe0ae56bf9546251339b0604b4e74078dd70c..6429b43be1980b60d7edaa6737606504c77d24e4 100644 (file)
@@ -1862,7 +1862,8 @@ pdp11_aout_swap_reloc_out (bfd *abfd, arelent *g, bfd_byte *natptr)
   if (r_extern)                                                                \
     {                                                                  \
       /* Undefined symbol.  */                                         \
-      cache_ptr->sym_ptr_ptr = symbols + r_index;                      \
+      if (r_index < bfd_get_symcount (abfd))                           \
+       cache_ptr->sym_ptr_ptr = symbols + r_index;                     \
       cache_ptr->addend = ad;                                          \
     }                                                                  \
   else                                                                 \