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 <m...@klomp.org> --- libelf/ChangeLog | 5 +++++ libelf/elf_begin.c | 16 ++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) 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 <m...@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 <m...@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) { -- 2.30.2