PTR_ADD and NPTR_ADD for bfd.h

Message ID YTBNcR8rzJ9iQlYG@squeak.grove.modra.org
State New
Headers show
Series
  • PTR_ADD and NPTR_ADD for bfd.h
Related show

Commit Message

Alan Modra via Binutils Sept. 2, 2021, 4:05 a.m.
This defines a couple of macros used to avoid ubsan complaints about
calculations involving NULL pointers.  PTR_ADD should be used in the
case where it is known that the offset is always zero with a NULL
pointer, and you'd like to know if a non-zero offset is ever used.
NPTR_ADD should be rarely used, but is defined for cases where a
non-zero offset is expected and should be ignored if the pointer is
NULL.

bfd/
	* bfd-in.h (PTR_ADD, NPTR_ADD): Define.
	* bfd-in2.h: Regenerate.
	* elf-eh-frame.c (adjust_eh_frame_local_symbols): Avoid NULL
	pointer calculations.
	* elflink.c (_bfd_elf_strip_zero_sized_dynamic_sections): Likewise.
	(bfd_elf_add_dt_needed_tag, elf_finalize_dynstr): Likewise.
	(elf_link_add_object_symbols, elf_link_input_bfd): Likewise.
	(bfd_elf_final_link, bfd_elf_gc_record_vtinherit): Likewise.
binutils/
	* objdump.c (disassemble_section): Use PTR_ADD for rel_ppend.


-- 
Alan Modra
Australia Development Lab, IBM

Patch

diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index a4888f9f7f2..12176433045 100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -113,6 +113,11 @@  typedef struct bfd bfd;
 # define TRUE 1
 #endif
 
+/* Silence "applying zero offset to null pointer" UBSAN warnings.  */
+#define PTR_ADD(P,A) ((A) ? (P) + (A) : (P))
+/* Also prevent non-zero offsets from being applied to a null pointer.  */
+#define NPTR_ADD(P,A) ((P) ? (P) + (A) : (P))
+
 #ifdef BFD64
 
 #ifndef BFD_HOST_64_BIT
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 4156f747ad4..a0faeafc3dc 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -120,6 +120,11 @@  typedef struct bfd bfd;
 # define TRUE 1
 #endif
 
+/* Silence "applying zero offset to null pointer" UBSAN warnings.  */
+#define PTR_ADD(P,A) ((A) ? (P) + (A) : (P))
+/* Also prevent non-zero offsets from being applied to a null pointer.  */
+#define NPTR_ADD(P,A) ((P) ? (P) + (A) : (P))
+
 #ifdef BFD64
 
 #ifndef BFD_HOST_64_BIT
diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
index 6ce6d225cff..b5ec81436c5 100644
--- a/bfd/elf-eh-frame.c
+++ b/bfd/elf-eh-frame.c
@@ -1440,25 +1440,27 @@  static int
 adjust_eh_frame_local_symbols (const asection *sec,
 			       struct elf_reloc_cookie *cookie)
 {
-  unsigned int shndx;
-  Elf_Internal_Sym *sym;
-  Elf_Internal_Sym *end_sym;
   int adjusted = 0;
 
-  shndx = elf_section_data (sec)->this_idx;
-  end_sym = cookie->locsyms + cookie->locsymcount;
-  for (sym = cookie->locsyms + 1; sym < end_sym; ++sym)
-    if (sym->st_info <= ELF_ST_INFO (STB_LOCAL, STT_OBJECT)
-	&& sym->st_shndx == shndx)
-      {
-	bfd_signed_vma delta = offset_adjust (sym->st_value, sec);
+  if (cookie->locsymcount > 1)
+    {
+      unsigned int shndx = elf_section_data (sec)->this_idx;
+      Elf_Internal_Sym *end_sym = cookie->locsyms + cookie->locsymcount;
+      Elf_Internal_Sym *sym;
 
-	if (delta != 0)
+      for (sym = cookie->locsyms + 1; sym < end_sym; ++sym)
+	if (sym->st_info <= ELF_ST_INFO (STB_LOCAL, STT_OBJECT)
+	    && sym->st_shndx == shndx)
 	  {
-	    adjusted = 1;
-	    sym->st_value += delta;
+	    bfd_signed_vma delta = offset_adjust (sym->st_value, sec);
+
+	    if (delta != 0)
+	      {
+		adjusted = 1;
+		sym->st_value += delta;
+	      }
 	  }
-      }
+    }
   return adjusted;
 }
 
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 6fe90412b28..354cebbe766 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -3649,7 +3649,7 @@  _bfd_elf_strip_zero_sized_dynamic_sections (struct bfd_link_info *info)
     else
       pp = &s->next;
 
-  if (strip_zero_sized_plt)
+  if (strip_zero_sized_plt && sdynamic->size != 0)
     for (extdyn = sdynamic->contents;
 	 extdyn < sdynamic->contents + sdynamic->size;
 	 extdyn = next)
@@ -3709,7 +3709,7 @@  bfd_elf_add_dt_needed_tag (bfd *abfd, struct bfd_link_info *info)
 
       bed = get_elf_backend_data (hash_table->dynobj);
       sdyn = bfd_get_linker_section (hash_table->dynobj, ".dynamic");
-      if (sdyn != NULL)
+      if (sdyn != NULL && sdyn->size != 0)
 	for (extdyn = sdyn->contents;
 	     extdyn < sdyn->contents + sdyn->size;
 	     extdyn += bed->s->sizeof_dyn)
@@ -3858,7 +3858,7 @@  elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info)
 
   /* Update all .dynamic entries referencing .dynstr strings.  */
   for (extdyn = sdyn->contents;
-       extdyn < sdyn->contents + sdyn->size;
+       extdyn < PTR_ADD (sdyn->contents, sdyn->size);
        extdyn += bed->s->sizeof_dyn)
     {
       Elf_Internal_Dyn dyn;
@@ -4276,7 +4276,7 @@  elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 		       | DYN_NO_NEEDED)) == 0;
 
       s = bfd_get_section_by_name (abfd, ".dynamic");
-      if (s != NULL)
+      if (s != NULL && s->size != 0)
 	{
 	  bfd_byte *dynbuf;
 	  bfd_byte *extdyn;
@@ -4650,7 +4650,7 @@  elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 	(_("%pB: plugin needed to handle lto object"), abfd);
     }
 
-  for (isym = isymbuf, isymend = isymbuf + extsymcount;
+  for (isym = isymbuf, isymend = PTR_ADD (isymbuf, extsymcount);
        isym < isymend;
        isym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL))
     {
@@ -10913,7 +10913,7 @@  elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
   /* Find local symbol sections and adjust values of symbols in
      SEC_MERGE sections.  Write out those local symbols we know are
      going into the output file.  */
-  isymend = isymbuf + locsymcount;
+  isymend = PTR_ADD (isymbuf, locsymcount);
   for (isym = isymbuf, pindex = flinfo->indices, ppsection = flinfo->sections;
        isym < isymend;
        isym++, pindex++, ppsection++)
@@ -11457,7 +11457,7 @@  elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 
 	      irela = internal_relocs;
 	      irelaend = irela + o->reloc_count;
-	      rel_hash = esdo->rel.hashes + esdo->rel.count;
+	      rel_hash = PTR_ADD (esdo->rel.hashes, esdo->rel.count);
 	      /* We start processing the REL relocs, if any.  When we reach
 		 IRELAMID in the loop, we switch to the RELA relocs.  */
 	      irelamid = irela;
@@ -11483,7 +11483,7 @@  elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 
 		  if (irela == irelamid)
 		    {
-		      rel_hash = esdo->rela.hashes + esdo->rela.count;
+		      rel_hash = PTR_ADD (esdo->rela.hashes, esdo->rela.count);
 		      rela_hash_list = rel_hash;
 		      rela_normal = bed->rela_normal;
 		    }
@@ -12957,7 +12957,7 @@  bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       BFD_ASSERT (o != NULL);
 
       dyncon = o->contents;
-      dynconend = o->contents + o->size;
+      dynconend = PTR_ADD (o->contents, o->size);
       for (; dyncon < dynconend; dyncon += bed->s->sizeof_dyn)
 	{
 	  Elf_Internal_Dyn dyn;
@@ -13160,7 +13160,8 @@  bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
       /* Check for DT_TEXTREL (late, in case the backend removes it).  */
       if (bfd_link_textrel_check (info)
-	  && (o = bfd_get_linker_section (dynobj, ".dynamic")) != NULL)
+	  && (o = bfd_get_linker_section (dynobj, ".dynamic")) != NULL
+	  && o->size != 0)
 	{
 	  bfd_byte *dyncon, *dynconend;
 
@@ -14206,7 +14207,7 @@  bfd_elf_gc_record_vtinherit (bfd *abfd,
     extsymcount -= elf_tdata (abfd)->symtab_hdr.sh_info;
 
   sym_hashes = elf_sym_hashes (abfd);
-  sym_hashes_end = sym_hashes + extsymcount;
+  sym_hashes_end = PTR_ADD (sym_hashes, extsymcount);
 
   /* Hunt down the child symbol, which is in this section at the same
      offset as the relocation.  */
diff --git a/binutils/objdump.c b/binutils/objdump.c
index f78b70a8d40..27bfb420399 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -3208,7 +3208,7 @@  disassemble_section (bfd *abfd, asection *section, void *inf)
 	    }
 	}
     }
-  rel_ppend = rel_pp + rel_count;
+  rel_ppend = PTR_ADD (rel_pp, rel_count);
 
   if (!bfd_malloc_and_get_section (abfd, section, &data))
     {