libelf: Only set shdr state when there is at least one shdr
authorMark Wielaard <mark@klomp.org>
Sun, 19 Dec 2021 14:52:32 +0000 (15:52 +0100)
committerMark Wielaard <mark@klomp.org>
Sun, 19 Dec 2021 14:52:32 +0000 (15:52 +0100)
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
libelf/elf_begin.c

index 617d97a..29a8aae 100644 (file)
@@ -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.
index bd3399d..0c9a988 100644 (file)
@@ -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)
            {