PR28403, null pointer dereference in disassemble_bytes

Message ID YVzzmvM4zA+zUMVD@squeak.grove.modra.org
State New
Headers show
Series
  • PR28403, null pointer dereference in disassemble_bytes
Related show

Commit Message

Alan Modra via Binutils Oct. 6, 2021, 12:53 a.m.
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.


-- 
Alan Modra
Australia Development Lab, IBM

Patch

diff --git a/bfd/aout-ns32k.c b/bfd/aout-ns32k.c
index 83fde67cc26..eb721b256d1 100644
--- a/bfd/aout-ns32k.c
+++ b/bfd/aout-ns32k.c
@@ -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);
diff --git a/bfd/aoutx.h b/bfd/aoutx.h
index 17560bd8f54..ea09646f2b3 100644
--- a/bfd/aoutx.h
+++ b/bfd/aoutx.h
@@ -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)
 			{
diff --git a/bfd/i386lynx.c b/bfd/i386lynx.c
index c477e661c81..932ce1741e2 100644
--- a/bfd/i386lynx.c
+++ b/bfd/i386lynx.c
@@ -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;
diff --git a/bfd/pdp11.c b/bfd/pdp11.c
index 2c9fe0ae56b..6429b43be19 100644
--- a/bfd/pdp11.c
+++ b/bfd/pdp11.c
@@ -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									\