diff mbox series

libelf: Only set shdr state when there is at least one shdr

Message ID 20211219145724.904346-1-mark@klomp.org
State Committed
Headers show
Series libelf: Only set shdr state when there is at least one shdr | expand

Commit Message

Mark Wielaard Dec. 19, 2021, 2:57 p.m. UTC
The elf shdr state only needs to be set when scncnt is at least
one. Otherwise e_shoff can be bogus. Also use unsigned arithmetic for
checking e_shoff alignment.

Signed-off-by: Mark Wielaard <mark@klomp.org>
---
 libelf/ChangeLog   |  5 +++++
 libelf/elf_begin.c | 16 ++++++++++------
 2 files changed, 15 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 617d97a5..29a8aae1 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,8 @@ 
+2021-12-19  Mark Wielaard  <mark@klomp.org>
+
+	* elf_begin.c (file_read_elf): Cast ehdr to uintptr_t before e_shoff
+	alignment check. Only set shdr state when scncnt is larger than zero.
+
 2021-12-16  Mark Wielaard  <mark@klomp.org>
 
 	* libelfP.h (NOTE_ALIGN4): And with negative unsigned long.
diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c
index bd3399de..0c9a988d 100644
--- a/libelf/elf_begin.c
+++ b/libelf/elf_begin.c
@@ -383,7 +383,7 @@  file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
       if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
 	  && cmd != ELF_C_READ_MMAP /* We need a copy to be able to write.  */
 	  && (ALLOW_UNALIGNED
-	      || (((uintptr_t) ((char *) ehdr + e_shoff)
+	      || ((((uintptr_t) ehdr + e_shoff)
 		   & (__alignof__ (Elf32_Shdr) - 1)) == 0)))
 	{
 	  if (unlikely (scncnt > 0 && e_shoff >= maxsize)
@@ -395,8 +395,10 @@  file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
 	      __libelf_seterrno (ELF_E_INVALID_ELF);
 	      return NULL;
 	    }
-	  elf->state.elf32.shdr
-	    = (Elf32_Shdr *) ((char *) ehdr + e_shoff);
+
+	  if (scncnt > 0)
+	    elf->state.elf32.shdr
+	      = (Elf32_Shdr *) ((char *) ehdr + e_shoff);
 
 	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
 	    {
@@ -485,15 +487,17 @@  file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
       if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
 	  && cmd != ELF_C_READ_MMAP /* We need a copy to be able to write.  */
 	  && (ALLOW_UNALIGNED
-	      || (((uintptr_t) ((char *) ehdr + e_shoff)
+	      || ((((uintptr_t) ehdr + e_shoff)
 		   & (__alignof__ (Elf64_Shdr) - 1)) == 0)))
 	{
 	  if (unlikely (scncnt > 0 && e_shoff >= maxsize)
 	      || unlikely (maxsize - e_shoff
 			   < scncnt * sizeof (Elf64_Shdr)))
 	    goto free_and_out;
-	  elf->state.elf64.shdr
-	    = (Elf64_Shdr *) ((char *) ehdr + e_shoff);
+
+	  if (scncnt > 0)
+	    elf->state.elf64.shdr
+	      = (Elf64_Shdr *) ((char *) ehdr + e_shoff);
 
 	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
 	    {