From 8707194a9f2f0b13e53041b03ebfdbdbd2942e43 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 5 Nov 2024 23:31:14 +0100 Subject: [PATCH 1/1] libelf: Only fetch shdr once in elf_compress[_gnu] Some compilers assume the second call to elf[32|64]_getshdr can fail and produce error: potential null pointer dereference. Just store the result of the first call and reuse (when not NULL). * libelf/elf_compress.c (elf_compress): Store getshdr result in a shdr union var. * libelf/elf_compress_gnu.c (): Likewise https://sourceware.org/bugzilla/show_bug.cgi?id=32311 Signed-off-by: Mark Wielaard --- libelf/elf_compress.c | 55 +++++++++++++++++++++------------------ libelf/elf_compress_gnu.c | 45 ++++++++++++++------------------ 2 files changed, 48 insertions(+), 52 deletions(-) --- a/libelf/elf_compress.c +++ b/libelf/elf_compress.c @@ -584,25 +584,30 @@ elf_compress (Elf_Scn *scn, int type, un Elf64_Xword sh_flags; Elf64_Word sh_type; Elf64_Xword sh_addralign; + union shdr + { + Elf32_Shdr *s32; + Elf64_Shdr *s64; + } shdr; if (elfclass == ELFCLASS32) { - Elf32_Shdr *shdr = elf32_getshdr (scn); - if (shdr == NULL) + shdr.s32 = elf32_getshdr (scn); + if (shdr.s32 == NULL) return -1; - sh_flags = shdr->sh_flags; - sh_type = shdr->sh_type; - sh_addralign = shdr->sh_addralign; + sh_flags = shdr.s32->sh_flags; + sh_type = shdr.s32->sh_type; + sh_addralign = shdr.s32->sh_addralign; } else { - Elf64_Shdr *shdr = elf64_getshdr (scn); - if (shdr == NULL) + shdr.s64 = elf64_getshdr (scn); + if (shdr.s64 == NULL) return -1; - sh_flags = shdr->sh_flags; - sh_type = shdr->sh_type; - sh_addralign = shdr->sh_addralign; + sh_flags = shdr.s64->sh_flags; + sh_type = shdr.s64->sh_type; + sh_addralign = shdr.s64->sh_addralign; } if ((sh_flags & SHF_ALLOC) != 0) @@ -679,17 +684,17 @@ elf_compress (Elf_Scn *scn, int type, un correctly and ignored when SHF_COMPRESSED is set. */ if (elfclass == ELFCLASS32) { - Elf32_Shdr *shdr = elf32_getshdr (scn); - shdr->sh_size = new_size; - shdr->sh_addralign = __libelf_type_align (ELFCLASS32, ELF_T_CHDR); - shdr->sh_flags |= SHF_COMPRESSED; + shdr.s32->sh_size = new_size; + shdr.s32->sh_addralign = __libelf_type_align (ELFCLASS32, + ELF_T_CHDR); + shdr.s32->sh_flags |= SHF_COMPRESSED; } else { - Elf64_Shdr *shdr = elf64_getshdr (scn); - shdr->sh_size = new_size; - shdr->sh_addralign = __libelf_type_align (ELFCLASS64, ELF_T_CHDR); - shdr->sh_flags |= SHF_COMPRESSED; + shdr.s64->sh_size = new_size; + shdr.s64->sh_addralign = __libelf_type_align (ELFCLASS64, + ELF_T_CHDR); + shdr.s64->sh_flags |= SHF_COMPRESSED; } __libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_CHDR); @@ -731,17 +736,15 @@ elf_compress (Elf_Scn *scn, int type, un correctly and ignored when SHF_COMPRESSED is set. */ if (elfclass == ELFCLASS32) { - Elf32_Shdr *shdr = elf32_getshdr (scn); - shdr->sh_size = scn->zdata_size; - shdr->sh_addralign = scn->zdata_align; - shdr->sh_flags &= ~SHF_COMPRESSED; + shdr.s32->sh_size = scn->zdata_size; + shdr.s32->sh_addralign = scn->zdata_align; + shdr.s32->sh_flags &= ~SHF_COMPRESSED; } else { - Elf64_Shdr *shdr = elf64_getshdr (scn); - shdr->sh_size = scn->zdata_size; - shdr->sh_addralign = scn->zdata_align; - shdr->sh_flags &= ~SHF_COMPRESSED; + shdr.s64->sh_size = scn->zdata_size; + shdr.s64->sh_addralign = scn->zdata_align; + shdr.s64->sh_flags &= ~SHF_COMPRESSED; } __libelf_reset_rawdata (scn, scn->zdata_base, --- a/libelf/elf_compress_gnu.c +++ b/libelf/elf_compress_gnu.c @@ -59,25 +59,30 @@ elf_compress_gnu (Elf_Scn *scn, int infl Elf64_Xword sh_flags; Elf64_Word sh_type; Elf64_Xword sh_addralign; + union shdr + { + Elf32_Shdr *s32; + Elf64_Shdr *s64; + } shdr; if (elfclass == ELFCLASS32) { - Elf32_Shdr *shdr = elf32_getshdr (scn); - if (shdr == NULL) + shdr.s32 = elf32_getshdr (scn); + if (shdr.s32 == NULL) return -1; - sh_flags = shdr->sh_flags; - sh_type = shdr->sh_type; - sh_addralign = shdr->sh_addralign; + sh_flags = shdr.s32->sh_flags; + sh_type = shdr.s32->sh_type; + sh_addralign = shdr.s32->sh_addralign; } else { - Elf64_Shdr *shdr = elf64_getshdr (scn); - if (shdr == NULL) + shdr.s64 = elf64_getshdr (scn); + if (shdr.s64 == NULL) return -1; - sh_flags = shdr->sh_flags; - sh_type = shdr->sh_type; - sh_addralign = shdr->sh_addralign; + sh_flags = shdr.s64->sh_flags; + sh_type = shdr.s64->sh_type; + sh_addralign = shdr.s64->sh_addralign; } /* Allocated sections, or sections that are already are compressed @@ -122,15 +127,9 @@ elf_compress_gnu (Elf_Scn *scn, int infl sh_flags won't have a SHF_COMPRESSED hint in the GNU format. Just adjust the sh_size. */ if (elfclass == ELFCLASS32) - { - Elf32_Shdr *shdr = elf32_getshdr (scn); - shdr->sh_size = new_size; - } + shdr.s32->sh_size = new_size; else - { - Elf64_Shdr *shdr = elf64_getshdr (scn); - shdr->sh_size = new_size; - } + shdr.s64->sh_size = new_size; __libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_BYTE); @@ -187,15 +186,9 @@ elf_compress_gnu (Elf_Scn *scn, int infl sh_flags won't have a SHF_COMPRESSED hint in the GNU format. Just adjust the sh_size. */ if (elfclass == ELFCLASS32) - { - Elf32_Shdr *shdr = elf32_getshdr (scn); - shdr->sh_size = size; - } + shdr.s32->sh_size = size; else - { - Elf64_Shdr *shdr = elf64_getshdr (scn); - shdr->sh_size = size; - } + shdr.s64->sh_size = size; __libelf_reset_rawdata (scn, buf_out, size, sh_addralign, __libelf_data_type (&ehdr, sh_type,