PR23199, Invalid SHT_GROUP entry leads to group confusion

Message ID 20180518090622.GQ23663@bubble.grove.modra.org
State New
Headers show
Series
  • PR23199, Invalid SHT_GROUP entry leads to group confusion
Related show

Commit Message

Alan Modra May 18, 2018, 9:06 a.m.
This patch prevents elf_next_in_group list pointer confusion when
SHT_GROUP sections specify other SHT_GROUP sections in their list of
group sections.

	PR 23199
	* elf.c (setup_group): Formatting.  Check that SHT_GROUP entries
	don't point at other SHT_GROUP sections.  Set shdr corresponding
	to invalid entry, to NULL rather than section 0.  Identify
	SHT_GROUP section index when reporting an error.  Cope with NULL
	shdr pointer.


-- 
Alan Modra
Australia Development Lab, IBM

Patch

diff --git a/bfd/elf.c b/bfd/elf.c
index 024b6cd86a..47d046fa83 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -628,7 +628,8 @@  setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
 	      bfd_alloc2 (abfd, num_group, sizeof (Elf_Internal_Shdr *));
 	  if (elf_tdata (abfd)->group_sect_ptr == NULL)
 	    return FALSE;
-	  memset (elf_tdata (abfd)->group_sect_ptr, 0, num_group * sizeof (Elf_Internal_Shdr *));
+	  memset (elf_tdata (abfd)->group_sect_ptr, 0,
+		  num_group * sizeof (Elf_Internal_Shdr *));
 	  num_group = 0;
 
 	  for (i = 0; i < shnum; i++)
@@ -709,13 +710,16 @@  setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
 			      |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
 			  break;
 			}
-		      if (idx >= shnum)
+		      if (idx < shnum)
+			dest->shdr = elf_elfsections (abfd)[idx];
+		      if (idx >= shnum
+			  || dest->shdr->sh_type == SHT_GROUP)
 			{
 			  _bfd_error_handler
-			    (_("%pB: invalid SHT_GROUP entry"), abfd);
-			  idx = 0;
+			    (_("%pB: invalid entry in SHT_GROUP section [%u]"),
+			       abfd, i);
+			  dest->shdr = NULL;
 			}
-		      dest->shdr = elf_elfsections (abfd)[idx];
 		    }
 		}
 	    }
@@ -781,7 +785,8 @@  setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
 		idx = (Elf_Internal_Group *) shdr->contents;
 		n_elt = shdr->sh_size / 4;
 		while (--n_elt != 0)
-		  if ((s = (++idx)->shdr->bfd_section) != NULL
+		  if ((++idx)->shdr != NULL
+		      && (s = idx->shdr->bfd_section) != NULL
 		      && elf_next_in_group (s) != NULL)
 		    break;
 		if (n_elt != 0)