public inbox for binutils-cvs@sourceware.org
 help / color / mirror / Atom feed
* [binutils-gdb] z8 and z80 coff_reloc16_extra_cases sanity checks
@ 2023-03-08  3:17 Alan Modra
  0 siblings, 0 replies; only message in thread
From: Alan Modra @ 2023-03-08  3:17 UTC (permalink / raw)
  To: bfd-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d64c8f7181fd21f90983f8d55369f6f9a2960c43

commit d64c8f7181fd21f90983f8d55369f6f9a2960c43
Author: Alan Modra <amodra@gmail.com>
Date:   Tue Mar 7 22:21:28 2023 +1030

    z8 and z80 coff_reloc16_extra_cases sanity checks
    
            * reloc16.c (bfd_coff_reloc16_get_relocated_section_contents):
            Use size_t variables.  Sanity check reloc address.  Handle
            errors from bfd_coff_reloc16_extra_cases.
            * coffcode.h (_bfd_coff_reloc16_extra_cases): Return bool, take
            size_t* args.
            (dummy_reloc16_extra_cases): Adjust to suit.  Don't abort.
            * coff-z80.c (extra_case): Sanity check reloc address.  Return
            errors.  Tidy formatting.  Use bfd_signed_vma temp var to
            check for reloc overflow.  Don't abort on unexpected reloc type,
            instead print an error and return false.
            * coff-z8k.c (extra_case): Likewise.
            * libcoff.h: Regenerate.

Diff:
---
 bfd/coff-z80.c | 118 +++++++++++++++++++++++++++------------------
 bfd/coff-z8k.c | 150 ++++++++++++++++++++++++++++++++-------------------------
 bfd/coffcode.h |  14 +++---
 bfd/libcoff.h  |   4 +-
 bfd/reloc16.c  |  28 +++++++----
 5 files changed, 182 insertions(+), 132 deletions(-)

diff --git a/bfd/coff-z80.c b/bfd/coff-z80.c
index c782e326bdb..702fe6550b5 100644
--- a/bfd/coff-z80.c
+++ b/bfd/coff-z80.c
@@ -330,77 +330,92 @@ reloc_processing (arelent *relent,
   relent->address -= section->vma;
 }
 
-static void
+static bool
 extra_case (bfd *in_abfd,
 	    struct bfd_link_info *link_info,
 	    struct bfd_link_order *link_order,
 	    arelent *reloc,
 	    bfd_byte *data,
-	    unsigned int *src_ptr,
-	    unsigned int *dst_ptr)
+	    size_t *src_ptr,
+	    size_t *dst_ptr)
 {
   asection * input_section = link_order->u.indirect.section;
-  int val = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
+  bfd_size_type end = bfd_get_section_limit_octets (in_abfd, input_section);
+  bfd_size_type reloc_size = bfd_get_reloc_size (reloc->howto);
+
+  if (*src_ptr > end
+      || reloc_size > end - *src_ptr)
+    {
+      link_info->callbacks->einfo
+	/* xgettext:c-format */
+	(_("%X%P: %pB(%pA): relocation \"%pR\" goes out of range\n"),
+	 in_abfd, input_section, reloc);
+      return false;
+    }
 
+  int val = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
   switch (reloc->howto->type)
     {
     case R_OFF8:
       if (reloc->howto->partial_inplace)
-        val += (signed char)(bfd_get_8 ( in_abfd, data+*src_ptr)
-                             & reloc->howto->src_mask);
-      if (val>127 || val<-128) /* Test for overflow.  */
-	  (*link_info->callbacks->reloc_overflow)
+	val += (signed char) (bfd_get_8 (in_abfd, data + *src_ptr)
+			      & reloc->howto->src_mask);
+      if (val > 127 || val < -128)
+	{
+	  link_info->callbacks->reloc_overflow
 	    (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
 	     reloc->howto->name, reloc->addend, input_section->owner,
 	     input_section, reloc->address);
+	  return false;
+	}
 
-	bfd_put_8 (in_abfd, val, data + *dst_ptr);
-	(*dst_ptr) += 1;
-	(*src_ptr) += 1;
+      bfd_put_8 (in_abfd, val, data + *dst_ptr);
+      *dst_ptr += 1;
+      *src_ptr += 1;
       break;
 
     case R_BYTE3:
       bfd_put_8 (in_abfd, val >> 24, data + *dst_ptr);
-      (*dst_ptr) += 1;
-      (*src_ptr) += 1;
+      *dst_ptr += 1;
+      *src_ptr += 1;
       break;
 
     case R_BYTE2:
       bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr);
-      (*dst_ptr) += 1;
-      (*src_ptr) += 1;
+      *dst_ptr += 1;
+      *src_ptr += 1;
       break;
 
     case R_BYTE1:
       bfd_put_8 (in_abfd, val >> 8, data + *dst_ptr);
-      (*dst_ptr) += 1;
-      (*src_ptr) += 1;
+      *dst_ptr += 1;
+      *src_ptr += 1;
       break;
 
     case R_IMM8:
       if (reloc->howto->partial_inplace)
-        val += bfd_get_8 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
+	val += bfd_get_8 (in_abfd, data + *src_ptr) & reloc->howto->src_mask;
       /* Fall through.  */
     case R_BYTE0:
       bfd_put_8 (in_abfd, val, data + *dst_ptr);
-      (*dst_ptr) += 1;
-      (*src_ptr) += 1;
+      *dst_ptr += 1;
+      *src_ptr += 1;
       break;
 
     case R_WORD1:
       bfd_put_16 (in_abfd, val >> 16, data + *dst_ptr);
-      (*dst_ptr) += 2;
-      (*src_ptr) += 2;
+      *dst_ptr += 2;
+      *src_ptr += 2;
       break;
 
     case R_IMM16:
       if (reloc->howto->partial_inplace)
-        val += bfd_get_16 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
+	val += bfd_get_16 (in_abfd, data + *src_ptr) & reloc->howto->src_mask;
       /* Fall through.  */
     case R_WORD0:
       bfd_put_16 (in_abfd, val, data + *dst_ptr);
-      (*dst_ptr) += 2;
-      (*src_ptr) += 2;
+      *dst_ptr += 2;
+      *src_ptr += 2;
       break;
 
     case R_IMM24:
@@ -408,53 +423,62 @@ extra_case (bfd *in_abfd,
 	val += (bfd_get_24 (in_abfd, data + *src_ptr)
 		& reloc->howto->src_mask);
       bfd_put_24 (in_abfd, val, data + *dst_ptr);
-      (*dst_ptr) += 3;
-      (*src_ptr) += 3;
+      *dst_ptr += 3;
+      *src_ptr += 3;
       break;
 
     case R_IMM32:
       if (reloc->howto->partial_inplace)
-        val += bfd_get_32 ( in_abfd, data+*src_ptr) & reloc->howto->src_mask;
+	val += bfd_get_32 (in_abfd, data + *src_ptr) & reloc->howto->src_mask;
       bfd_put_32 (in_abfd, val, data + *dst_ptr);
-      (*dst_ptr) += 4;
-      (*src_ptr) += 4;
+      *dst_ptr += 4;
+      *src_ptr += 4;
       break;
 
     case R_JR:
       {
-        if (reloc->howto->partial_inplace)
-          val += (signed char)(bfd_get_8 ( in_abfd, data+*src_ptr) 
-                               & reloc->howto->src_mask);
+	if (reloc->howto->partial_inplace)
+	  val += (signed char) (bfd_get_8 (in_abfd, data + *src_ptr)
+				& reloc->howto->src_mask);
 	bfd_vma dot = (*dst_ptr
 		       + input_section->output_offset
 		       + input_section->output_section->vma);
-	int gap = val - dot;
+	bfd_signed_vma gap = val - dot;
 	if (gap >= 128 || gap < -128)
-	  (*link_info->callbacks->reloc_overflow)
-	    (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
-	     reloc->howto->name, reloc->addend, input_section->owner,
-	     input_section, reloc->address);
+	  {
+	    link_info->callbacks->reloc_overflow
+	      (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+	       reloc->howto->name, reloc->addend, input_section->owner,
+	       input_section, reloc->address);
+	    return false;
+	  }
 
 	bfd_put_8 (in_abfd, gap, data + *dst_ptr);
-	(*dst_ptr)++;
-	(*src_ptr)++;
+	*dst_ptr += 1;
+	*src_ptr += 1;
 	break;
       }
 
     case R_IMM16BE:
       if (reloc->howto->partial_inplace)
-	val += (bfd_get_8 ( in_abfd, data+*src_ptr+0) * 0x100 +
-		bfd_get_8 ( in_abfd, data+*src_ptr+1)) & reloc->howto->src_mask;
+	val += ((bfd_get_8 (in_abfd, data + *src_ptr + 0) * 0x100
+		 + bfd_get_8 (in_abfd, data + *src_ptr + 1))
+		& reloc->howto->src_mask);
       
-      bfd_put_8 (in_abfd, val >> 8, data + *dst_ptr+0);
-      bfd_put_8 (in_abfd, val, data + *dst_ptr+1);
-      (*dst_ptr) += 2;
-      (*src_ptr) += 2;
+      bfd_put_8 (in_abfd, val >> 8, data + *dst_ptr + 0);
+      bfd_put_8 (in_abfd, val, data + *dst_ptr + 1);
+      *dst_ptr += 2;
+      *src_ptr += 2;
       break;
 
     default:
-      abort ();
+      link_info->callbacks->einfo
+	/* xgettext:c-format */
+	(_("%X%P: %pB(%pA): relocation \"%pR\" is not supported\n"),
+	 in_abfd, input_section, reloc);
+      return false;
     }
+  return true;
 }
 
 static bool
diff --git a/bfd/coff-z8k.c b/bfd/coff-z8k.c
index d030056f372..f50e1c819ae 100644
--- a/bfd/coff-z8k.c
+++ b/bfd/coff-z8k.c
@@ -193,16 +193,28 @@ reloc_processing (arelent *relent,
   relent->address -= section->vma;
 }
 
-static void
+static bool
 extra_case (bfd *in_abfd,
 	    struct bfd_link_info *link_info,
 	    struct bfd_link_order *link_order,
 	    arelent *reloc,
 	    bfd_byte *data,
-	    unsigned int *src_ptr,
-	    unsigned int *dst_ptr)
+	    size_t *src_ptr,
+	    size_t *dst_ptr)
 {
   asection * input_section = link_order->u.indirect.section;
+  bfd_size_type end = bfd_get_section_limit_octets (in_abfd, input_section);
+  bfd_size_type reloc_size = bfd_get_reloc_size (reloc->howto);
+
+  if (*src_ptr > end
+      || reloc_size > end - *src_ptr)
+    {
+      link_info->callbacks->einfo
+	/* xgettext:c-format */
+	(_("%X%P: %pB(%pA): relocation \"%pR\" goes out of range\n"),
+	 in_abfd, input_section, reloc);
+      return false;
+    }
 
   switch (reloc->howto->type)
     {
@@ -210,8 +222,8 @@ extra_case (bfd *in_abfd,
       bfd_put_8 (in_abfd,
 		 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
 		 data + *dst_ptr);
-      (*dst_ptr) += 1;
-      (*src_ptr) += 1;
+      *dst_ptr += 1;
+      *src_ptr += 1;
       break;
 
     case R_IMM32:
@@ -234,27 +246,26 @@ extra_case (bfd *in_abfd,
 	  dst = (dst & 0xffff) | ((dst & 0xff0000) << 8) | 0x80000000;
 	  bfd_put_32 (in_abfd, dst, data + *dst_ptr);
 	}
-      (*dst_ptr) += 4;
-      (*src_ptr) += 4;
+      *dst_ptr += 4;
+      *src_ptr += 4;
       break;
 
     case R_IMM4L:
       bfd_put_8 (in_abfd,
 		 ((bfd_get_8 (in_abfd, data + *dst_ptr) & 0xf0)
-		  | (0x0f
-		     & bfd_coff_reloc16_get_value (reloc, link_info,
-						   input_section))),
+		  | (0x0f & bfd_coff_reloc16_get_value (reloc, link_info,
+							input_section))),
 		 data + *dst_ptr);
-      (*dst_ptr) += 1;
-      (*src_ptr) += 1;
+      *dst_ptr += 1;
+      *src_ptr += 1;
       break;
 
     case R_IMM16:
       bfd_put_16 (in_abfd,
 		  bfd_coff_reloc16_get_value (reloc, link_info, input_section),
 		  data + *dst_ptr);
-      (*dst_ptr) += 2;
-      (*src_ptr) += 2;
+      *dst_ptr += 2;
+      *src_ptr += 2;
       break;
 
     case R_JR:
@@ -264,21 +275,22 @@ extra_case (bfd *in_abfd,
 	bfd_vma dot = (*dst_ptr
 		       + input_section->output_offset
 		       + input_section->output_section->vma);
-	int gap = dst - dot - 1;  /* -1, since we're in the odd byte of the
-				     word and the pc's been incremented.  */
-
-	if (gap & 1)
-	  abort ();
-	gap /= 2;
-	if (gap > 127 || gap < -128)
-	  (*link_info->callbacks->reloc_overflow)
-	    (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
-	     reloc->howto->name, reloc->addend, input_section->owner,
-	     input_section, reloc->address);
-
-	bfd_put_8 (in_abfd, gap, data + *dst_ptr);
-	(*dst_ptr)++;
-	(*src_ptr)++;
+	/* -1, since we're in the odd byte of the word and the pc has
+	   been incremented.  */
+	bfd_signed_vma gap = dst - dot - 1;
+
+	if ((gap & 1) != 0 || gap > 254 || gap < -256)
+	  {
+	    link_info->callbacks->reloc_overflow
+	      (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+	       reloc->howto->name, reloc->addend, input_section->owner,
+	       input_section, reloc->address);
+	    return false;
+	  }
+
+	bfd_put_8 (in_abfd, gap / 2, data + *dst_ptr);
+	*dst_ptr += 1;
+	*src_ptr += 1;
 	break;
       }
 
@@ -289,24 +301,23 @@ extra_case (bfd *in_abfd,
 	bfd_vma dot = (*dst_ptr
 		       + input_section->output_offset
 		       + input_section->output_section->vma);
-	int gap = dst - dot - 1;  /* -1, since we're in the odd byte of the
-				     word and the pc's been incremented.  */
-
-	if (gap & 1)
-	  abort ();
-	gap /= 2;
+	bfd_signed_vma gap = dst - dot - 1;
 
-	if (gap > 0 || gap < -127)
-	  (*link_info->callbacks->reloc_overflow)
-	    (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
-	     reloc->howto->name, reloc->addend, input_section->owner,
-	     input_section, reloc->address);
+	if ((gap & 1) != 0 || gap > 0 || gap < -254)
+	  {
+	    link_info->callbacks->reloc_overflow
+	      (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+	       reloc->howto->name, reloc->addend, input_section->owner,
+	       input_section, reloc->address);
+	    return false;
+	  }
 
 	bfd_put_8 (in_abfd,
-		   (bfd_get_8 ( in_abfd, data + *dst_ptr) & 0x80) + (-gap & 0x7f),
+		   ((bfd_get_8 (in_abfd, data + *dst_ptr) & 0x80)
+		    + (-gap / 2 & 0x7f)),
 		   data + *dst_ptr);
-	(*dst_ptr)++;
-	(*src_ptr)++;
+	*dst_ptr += 1;
+	*src_ptr += 1;
 	break;
       }
 
@@ -317,22 +328,23 @@ extra_case (bfd *in_abfd,
 	bfd_vma dot = (*dst_ptr
 		       + input_section->output_offset
 		       + input_section->output_section->vma);
-	int gap = dst - dot - 2;
+	bfd_signed_vma gap = dst - dot - 2;
 
-	if (gap & 1)
-	  abort ();
-	if (gap > 4096 || gap < -4095)
-	  (*link_info->callbacks->reloc_overflow)
-	    (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
-	     reloc->howto->name, reloc->addend, input_section->owner,
-	     input_section, reloc->address);
+	if ((gap & 1) != 0 || gap > 4096 || gap < -4095)
+	  {
+	    link_info->callbacks->reloc_overflow
+	      (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+	       reloc->howto->name, reloc->addend, input_section->owner,
+	       input_section, reloc->address);
+	    return false;
+	  }
 
-	gap /= 2;
 	bfd_put_16 (in_abfd,
-		    (bfd_get_16 ( in_abfd, data + *dst_ptr) & 0xf000) | (-gap & 0x0fff),
+		    ((bfd_get_16 (in_abfd, data + *dst_ptr) & 0xf000)
+		     | (-gap / 2 & 0x0fff)),
 		    data + *dst_ptr);
-	(*dst_ptr) += 2;
-	(*src_ptr) += 2;
+	*dst_ptr += 2;
+	*src_ptr += 2;
 	break;
       }
 
@@ -343,23 +355,31 @@ extra_case (bfd *in_abfd,
 	bfd_vma dot = (*dst_ptr
 		       + input_section->output_offset
 		       + input_section->output_section->vma);
-	int gap = dst - dot - 2;
+	bfd_signed_vma gap = dst - dot - 2;
 
 	if (gap > 32767 || gap < -32768)
-	  (*link_info->callbacks->reloc_overflow)
-	    (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
-	     reloc->howto->name, reloc->addend, input_section->owner,
-	     input_section, reloc->address);
-
-	bfd_put_16 (in_abfd, (bfd_vma) gap, data + *dst_ptr);
-	(*dst_ptr) += 2;
-	(*src_ptr) += 2;
+	  {
+	    link_info->callbacks->reloc_overflow
+	      (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+	       reloc->howto->name, reloc->addend, input_section->owner,
+	       input_section, reloc->address);
+	    return false;
+	  }
+
+	bfd_put_16 (in_abfd, gap, data + *dst_ptr);
+	*dst_ptr += 2;
+	*src_ptr += 2;
 	break;
       }
 
     default:
-      abort ();
+      link_info->callbacks->einfo
+	/* xgettext:c-format */
+	(_("%X%P: %pB(%pA): relocation \"%pR\" is not supported\n"),
+	 in_abfd, input_section, reloc);
+      return false;
     }
+  return true;
 }
 
 #define coff_reloc16_extra_cases    extra_case
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index c4f7d199c82..7a4c409a756 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -1495,9 +1495,9 @@ Special entry points for gdb to swap in coff symbol table parts:
 .    (bfd *, FILE *, combined_entry_type *, combined_entry_type *,
 .     combined_entry_type *, unsigned int);
 .
-.  void (*_bfd_coff_reloc16_extra_cases)
+.  bool (*_bfd_coff_reloc16_extra_cases)
 .    (bfd *, struct bfd_link_info *, struct bfd_link_order *, arelent *,
-.     bfd_byte *, unsigned int *, unsigned int *);
+.     bfd_byte *, size_t *, size_t *);
 .
 .  int (*_bfd_coff_reloc16_estimate)
 .    (bfd *, asection *, arelent *, unsigned int,
@@ -5331,18 +5331,16 @@ dummy_reloc16_estimate (bfd *abfd ATTRIBUTE_UNUSED,
 
 #define coff_reloc16_extra_cases dummy_reloc16_extra_cases
 
-/* This works even if abort is not declared in any header file.  */
-
-static void
+static bool
 dummy_reloc16_extra_cases (bfd *abfd ATTRIBUTE_UNUSED,
 			   struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
 			   struct bfd_link_order *link_order ATTRIBUTE_UNUSED,
 			   arelent *reloc ATTRIBUTE_UNUSED,
 			   bfd_byte *data ATTRIBUTE_UNUSED,
-			   unsigned int *src_ptr ATTRIBUTE_UNUSED,
-			   unsigned int *dst_ptr ATTRIBUTE_UNUSED)
+			   size_t *src_ptr ATTRIBUTE_UNUSED,
+			   size_t *dst_ptr ATTRIBUTE_UNUSED)
 {
-  abort ();
+  return false;
 }
 #endif
 
diff --git a/bfd/libcoff.h b/bfd/libcoff.h
index c2c1f4add3a..b7a4f677411 100644
--- a/bfd/libcoff.h
+++ b/bfd/libcoff.h
@@ -801,9 +801,9 @@ typedef struct
     (bfd *, FILE *, combined_entry_type *, combined_entry_type *,
      combined_entry_type *, unsigned int);
 
-  void (*_bfd_coff_reloc16_extra_cases)
+  bool (*_bfd_coff_reloc16_extra_cases)
     (bfd *, struct bfd_link_info *, struct bfd_link_order *, arelent *,
-     bfd_byte *, unsigned int *, unsigned int *);
+     bfd_byte *, size_t *, size_t *);
 
   int (*_bfd_coff_reloc16_estimate)
     (bfd *, asection *, arelent *, unsigned int,
diff --git a/bfd/reloc16.c b/bfd/reloc16.c
index fb4c04d558e..3b4e483f75e 100644
--- a/bfd/reloc16.c
+++ b/bfd/reloc16.c
@@ -292,10 +292,10 @@ bfd_coff_reloc16_get_relocated_section_contents
     {
       arelent **parent = reloc_vector;
       arelent *reloc;
-      unsigned int dst_address = 0;
-      unsigned int src_address = 0;
-      unsigned int run;
-      unsigned int idx;
+      size_t dst_address = 0;
+      size_t src_address = 0;
+      size_t run;
+      size_t idx;
 
       /* Find how long a run we can do.  */
       while (dst_address < link_order->size)
@@ -306,6 +306,15 @@ bfd_coff_reloc16_get_relocated_section_contents
 	      /* Note that the relaxing didn't tie up the addresses in the
 		 relocation, so we use the original address to work out the
 		 run of non-relocated data.  */
+	      if (reloc->address > link_order->size
+		  || reloc->address < src_address)
+		{
+		  link_info->callbacks->einfo
+		    /* xgettext:c-format */
+		    (_("%X%P: %pB(%pA): relocation \"%pR\" goes out of range\n"),
+		     input_bfd, input_section, reloc);
+		  goto error_return;
+		}
 	      run = reloc->address - src_address;
 	      parent++;
 	    }
@@ -319,12 +328,11 @@ bfd_coff_reloc16_get_relocated_section_contents
 	    data[dst_address++] = data[src_address++];
 
 	  /* Now do the relocation.  */
-	  if (reloc)
-	    {
-	      bfd_coff_reloc16_extra_cases (input_bfd, link_info, link_order,
-					    reloc, data, &src_address,
-					    &dst_address);
-	    }
+	  if (reloc
+	      && !bfd_coff_reloc16_extra_cases (input_bfd, link_info,
+						link_order, reloc, data,
+						&src_address, &dst_address))
+	    goto error_return;
 	}
     }
   free (reloc_vector);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-03-08  3:17 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-08  3:17 [binutils-gdb] z8 and z80 coff_reloc16_extra_cases sanity checks Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).