blob: 1179a1e1a01f67a5837311bf9b1b4cf818695791 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001From 8707194a9f2f0b13e53041b03ebfdbdbd2942e43 Mon Sep 17 00:00:00 2001
2From: Mark Wielaard <mark@klomp.org>
3Date: Tue, 5 Nov 2024 23:31:14 +0100
4Subject: [PATCH 1/1] libelf: Only fetch shdr once in elf_compress[_gnu]
5
6Some compilers assume the second call to elf[32|64]_getshdr can fail
7and produce error: potential null pointer dereference. Just store the
8result of the first call and reuse (when not NULL).
9
10 * libelf/elf_compress.c (elf_compress): Store getshdr result in
11 a shdr union var.
12 * libelf/elf_compress_gnu.c (): Likewise
13
14https://sourceware.org/bugzilla/show_bug.cgi?id=32311
15
16Signed-off-by: Mark Wielaard <mark@klomp.org>
17---
18 libelf/elf_compress.c | 55 +++++++++++++++++++++------------------
19 libelf/elf_compress_gnu.c | 45 ++++++++++++++------------------
20 2 files changed, 48 insertions(+), 52 deletions(-)
21
22--- a/libelf/elf_compress.c
23+++ b/libelf/elf_compress.c
24@@ -584,25 +584,30 @@ elf_compress (Elf_Scn *scn, int type, un
25 Elf64_Xword sh_flags;
26 Elf64_Word sh_type;
27 Elf64_Xword sh_addralign;
28+ union shdr
29+ {
30+ Elf32_Shdr *s32;
31+ Elf64_Shdr *s64;
32+ } shdr;
33 if (elfclass == ELFCLASS32)
34 {
35- Elf32_Shdr *shdr = elf32_getshdr (scn);
36- if (shdr == NULL)
37+ shdr.s32 = elf32_getshdr (scn);
38+ if (shdr.s32 == NULL)
39 return -1;
40
41- sh_flags = shdr->sh_flags;
42- sh_type = shdr->sh_type;
43- sh_addralign = shdr->sh_addralign;
44+ sh_flags = shdr.s32->sh_flags;
45+ sh_type = shdr.s32->sh_type;
46+ sh_addralign = shdr.s32->sh_addralign;
47 }
48 else
49 {
50- Elf64_Shdr *shdr = elf64_getshdr (scn);
51- if (shdr == NULL)
52+ shdr.s64 = elf64_getshdr (scn);
53+ if (shdr.s64 == NULL)
54 return -1;
55
56- sh_flags = shdr->sh_flags;
57- sh_type = shdr->sh_type;
58- sh_addralign = shdr->sh_addralign;
59+ sh_flags = shdr.s64->sh_flags;
60+ sh_type = shdr.s64->sh_type;
61+ sh_addralign = shdr.s64->sh_addralign;
62 }
63
64 if ((sh_flags & SHF_ALLOC) != 0)
65@@ -679,17 +684,17 @@ elf_compress (Elf_Scn *scn, int type, un
66 correctly and ignored when SHF_COMPRESSED is set. */
67 if (elfclass == ELFCLASS32)
68 {
69- Elf32_Shdr *shdr = elf32_getshdr (scn);
70- shdr->sh_size = new_size;
71- shdr->sh_addralign = __libelf_type_align (ELFCLASS32, ELF_T_CHDR);
72- shdr->sh_flags |= SHF_COMPRESSED;
73+ shdr.s32->sh_size = new_size;
74+ shdr.s32->sh_addralign = __libelf_type_align (ELFCLASS32,
75+ ELF_T_CHDR);
76+ shdr.s32->sh_flags |= SHF_COMPRESSED;
77 }
78 else
79 {
80- Elf64_Shdr *shdr = elf64_getshdr (scn);
81- shdr->sh_size = new_size;
82- shdr->sh_addralign = __libelf_type_align (ELFCLASS64, ELF_T_CHDR);
83- shdr->sh_flags |= SHF_COMPRESSED;
84+ shdr.s64->sh_size = new_size;
85+ shdr.s64->sh_addralign = __libelf_type_align (ELFCLASS64,
86+ ELF_T_CHDR);
87+ shdr.s64->sh_flags |= SHF_COMPRESSED;
88 }
89
90 __libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_CHDR);
91@@ -731,17 +736,15 @@ elf_compress (Elf_Scn *scn, int type, un
92 correctly and ignored when SHF_COMPRESSED is set. */
93 if (elfclass == ELFCLASS32)
94 {
95- Elf32_Shdr *shdr = elf32_getshdr (scn);
96- shdr->sh_size = scn->zdata_size;
97- shdr->sh_addralign = scn->zdata_align;
98- shdr->sh_flags &= ~SHF_COMPRESSED;
99+ shdr.s32->sh_size = scn->zdata_size;
100+ shdr.s32->sh_addralign = scn->zdata_align;
101+ shdr.s32->sh_flags &= ~SHF_COMPRESSED;
102 }
103 else
104 {
105- Elf64_Shdr *shdr = elf64_getshdr (scn);
106- shdr->sh_size = scn->zdata_size;
107- shdr->sh_addralign = scn->zdata_align;
108- shdr->sh_flags &= ~SHF_COMPRESSED;
109+ shdr.s64->sh_size = scn->zdata_size;
110+ shdr.s64->sh_addralign = scn->zdata_align;
111+ shdr.s64->sh_flags &= ~SHF_COMPRESSED;
112 }
113
114 __libelf_reset_rawdata (scn, scn->zdata_base,
115--- a/libelf/elf_compress_gnu.c
116+++ b/libelf/elf_compress_gnu.c
117@@ -59,25 +59,30 @@ elf_compress_gnu (Elf_Scn *scn, int infl
118 Elf64_Xword sh_flags;
119 Elf64_Word sh_type;
120 Elf64_Xword sh_addralign;
121+ union shdr
122+ {
123+ Elf32_Shdr *s32;
124+ Elf64_Shdr *s64;
125+ } shdr;
126 if (elfclass == ELFCLASS32)
127 {
128- Elf32_Shdr *shdr = elf32_getshdr (scn);
129- if (shdr == NULL)
130+ shdr.s32 = elf32_getshdr (scn);
131+ if (shdr.s32 == NULL)
132 return -1;
133
134- sh_flags = shdr->sh_flags;
135- sh_type = shdr->sh_type;
136- sh_addralign = shdr->sh_addralign;
137+ sh_flags = shdr.s32->sh_flags;
138+ sh_type = shdr.s32->sh_type;
139+ sh_addralign = shdr.s32->sh_addralign;
140 }
141 else
142 {
143- Elf64_Shdr *shdr = elf64_getshdr (scn);
144- if (shdr == NULL)
145+ shdr.s64 = elf64_getshdr (scn);
146+ if (shdr.s64 == NULL)
147 return -1;
148
149- sh_flags = shdr->sh_flags;
150- sh_type = shdr->sh_type;
151- sh_addralign = shdr->sh_addralign;
152+ sh_flags = shdr.s64->sh_flags;
153+ sh_type = shdr.s64->sh_type;
154+ sh_addralign = shdr.s64->sh_addralign;
155 }
156
157 /* Allocated sections, or sections that are already are compressed
158@@ -122,15 +127,9 @@ elf_compress_gnu (Elf_Scn *scn, int infl
159 sh_flags won't have a SHF_COMPRESSED hint in the GNU format.
160 Just adjust the sh_size. */
161 if (elfclass == ELFCLASS32)
162- {
163- Elf32_Shdr *shdr = elf32_getshdr (scn);
164- shdr->sh_size = new_size;
165- }
166+ shdr.s32->sh_size = new_size;
167 else
168- {
169- Elf64_Shdr *shdr = elf64_getshdr (scn);
170- shdr->sh_size = new_size;
171- }
172+ shdr.s64->sh_size = new_size;
173
174 __libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_BYTE);
175
176@@ -187,15 +186,9 @@ elf_compress_gnu (Elf_Scn *scn, int infl
177 sh_flags won't have a SHF_COMPRESSED hint in the GNU format.
178 Just adjust the sh_size. */
179 if (elfclass == ELFCLASS32)
180- {
181- Elf32_Shdr *shdr = elf32_getshdr (scn);
182- shdr->sh_size = size;
183- }
184+ shdr.s32->sh_size = size;
185 else
186- {
187- Elf64_Shdr *shdr = elf64_getshdr (scn);
188- shdr->sh_size = size;
189- }
190+ shdr.s64->sh_size = size;
191
192 __libelf_reset_rawdata (scn, buf_out, size, sh_addralign,
193 __libelf_data_type (&ehdr, sh_type,