Branch data Line data Source code
1 : : /* Conversion functions for versioning information.
2 : : Copyright (C) 1998, 1999, 2000, 2002, 2003, 2015 Red Hat, Inc.
3 : : Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
4 : : This file is part of elfutils.
5 : : Written by Ulrich Drepper <drepper@redhat.com>, 1998.
6 : :
7 : : This file is free software; you can redistribute it and/or modify
8 : : it under the terms of either
9 : :
10 : : * the GNU Lesser General Public License as published by the Free
11 : : Software Foundation; either version 3 of the License, or (at
12 : : your option) any later version
13 : :
14 : : or
15 : :
16 : : * the GNU General Public License as published by the Free
17 : : Software Foundation; either version 2 of the License, or (at
18 : : your option) any later version
19 : :
20 : : or both in parallel, as here.
21 : :
22 : : elfutils is distributed in the hope that it will be useful, but
23 : : WITHOUT ANY WARRANTY; without even the implied warranty of
24 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 : : General Public License for more details.
26 : :
27 : : You should have received copies of the GNU General Public License and
28 : : the GNU Lesser General Public License along with this program. If
29 : : not, see <http://www.gnu.org/licenses/>. */
30 : :
31 : : #include <gelf.h>
32 : :
33 : : #include "libelfP.h"
34 : :
35 : :
36 : : static void
37 : 22 : elf_cvt_Verdef (void *dest, const void *src, size_t len, int encode)
38 : : {
39 : : /* We have two different record types: ElfXX_Verndef and ElfXX_Verdaux.
40 : : To recognize them we have to walk the data structure and convert
41 : : them one after the other. The ENCODE parameter specifies whether
42 : : we are encoding or decoding. When we are encoding we can immediately
43 : : use the data in the buffer; if not, we have to decode the data before
44 : : using it. */
45 : 22 : size_t def_offset = 0;
46 : 22 : GElf_Verdef *ddest;
47 : 22 : GElf_Verdef *dsrc;
48 : :
49 : : /* We rely on the types being all the same size. */
50 : 22 : eu_static_assert (sizeof (GElf_Verdef) == sizeof (Elf32_Verdef));
51 : 22 : eu_static_assert (sizeof (GElf_Verdaux) == sizeof (Elf32_Verdaux));
52 : 22 : eu_static_assert (sizeof (GElf_Verdef) == sizeof (Elf64_Verdef));
53 : 22 : eu_static_assert (sizeof (GElf_Verdaux) == sizeof (Elf64_Verdaux));
54 : :
55 [ + - ]: 22 : if (len == 0)
56 : : return;
57 : :
58 : : /* Below we rely on the next field offsets to be correct, start by
59 : : copying over all data as is in case some data isn't translated.
60 : : We don't want to leave (undefined) garbage in the dest buffer. */
61 : 22 : memmove (dest, src, len);
62 : :
63 : 44 : do
64 : : {
65 : 44 : size_t aux_offset;
66 : 44 : GElf_Verdaux *asrc;
67 : :
68 : : /* Test for correct offset. */
69 [ + - ]: 44 : if (def_offset > len
70 [ + - ]: 44 : || len - def_offset < sizeof (GElf_Verdef)
71 [ + - ]: 44 : || (def_offset & (__alignof__ (GElf_Verdef) - 1)) != 0)
72 : : return;
73 : :
74 : : /* Work the tree from the first record. */
75 : 44 : ddest = (GElf_Verdef *) ((char *) dest + def_offset);
76 : 44 : dsrc = (GElf_Verdef *) ((char *) src + def_offset);
77 : :
78 : : /* Decode first if necessary. */
79 [ + + ]: 44 : if (! encode)
80 : : {
81 [ + - ]: 28 : ddest->vd_version = bswap_16 (dsrc->vd_version);
82 : 28 : ddest->vd_flags = bswap_16 (dsrc->vd_flags);
83 : 28 : ddest->vd_ndx = bswap_16 (dsrc->vd_ndx);
84 : 28 : ddest->vd_cnt = bswap_16 (dsrc->vd_cnt);
85 [ + - ]: 28 : ddest->vd_hash = bswap_32 (dsrc->vd_hash);
86 : 28 : ddest->vd_aux = bswap_32 (dsrc->vd_aux);
87 : 28 : ddest->vd_next = bswap_32 (dsrc->vd_next);
88 : :
89 [ + - ]: 28 : if (ddest->vd_aux > len - def_offset)
90 : : return;
91 : 28 : aux_offset = def_offset + ddest->vd_aux;
92 : : }
93 : : else
94 : : {
95 [ + - ]: 16 : if (dsrc->vd_aux > len - def_offset)
96 : : return;
97 : 16 : aux_offset = def_offset + dsrc->vd_aux;
98 : : }
99 : :
100 : : /* Handle all the auxiliary records belonging to this definition. */
101 : 44 : do
102 : : {
103 : 44 : GElf_Verdaux *adest;
104 : :
105 : : /* Test for correct offset. */
106 [ + - ]: 44 : if (aux_offset > len
107 [ + - ]: 44 : || len - aux_offset < sizeof (GElf_Verdaux)
108 [ + - ]: 44 : || (aux_offset & (__alignof__ (GElf_Verdaux) - 1)) != 0)
109 : : return;
110 : :
111 : 44 : adest = (GElf_Verdaux *) ((char *) dest + aux_offset);
112 : 44 : asrc = (GElf_Verdaux *) ((char *) src + aux_offset);
113 : :
114 [ + + ]: 44 : if (encode)
115 : : {
116 [ + - ]: 16 : if (asrc->vda_next > len - aux_offset)
117 : : return;
118 : 16 : aux_offset += asrc->vda_next;
119 : : }
120 : :
121 [ + + ]: 44 : adest->vda_name = bswap_32 (asrc->vda_name);
122 : 44 : adest->vda_next = bswap_32 (asrc->vda_next);
123 : :
124 [ + + ]: 44 : if (! encode)
125 : : {
126 [ + - ]: 28 : if (adest->vda_next > len - aux_offset)
127 : : return;
128 : 28 : aux_offset += adest->vda_next;
129 : : }
130 : : }
131 [ - + ]: 44 : while (asrc->vda_next != 0);
132 : :
133 : : /* Encode now if necessary. */
134 [ + + ]: 44 : if (encode)
135 : : {
136 [ + - ]: 16 : if (dsrc->vd_next > len - def_offset)
137 : : return;
138 : 16 : def_offset += dsrc->vd_next;
139 : :
140 : 16 : ddest->vd_version = bswap_16 (dsrc->vd_version);
141 : 16 : ddest->vd_flags = bswap_16 (dsrc->vd_flags);
142 : 16 : ddest->vd_ndx = bswap_16 (dsrc->vd_ndx);
143 : 16 : ddest->vd_cnt = bswap_16 (dsrc->vd_cnt);
144 : 16 : ddest->vd_hash = bswap_32 (dsrc->vd_hash);
145 : 16 : ddest->vd_aux = bswap_32 (dsrc->vd_aux);
146 : 16 : ddest->vd_next = bswap_32 (dsrc->vd_next);
147 : : }
148 : : else
149 : : {
150 [ + - ]: 28 : if (ddest->vd_next > len - def_offset)
151 : : return;
152 : 28 : def_offset += ddest->vd_next;
153 : : }
154 : : }
155 [ + + ]: 44 : while (dsrc->vd_next != 0);
156 : : }
157 : :
158 : :
159 : : static void
160 : 404 : elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
161 : : {
162 : : /* We have two different record types: ElfXX_Verndef and ElfXX_Verdaux.
163 : : To recognize them we have to walk the data structure and convert
164 : : them one after the other. The ENCODE parameter specifies whether
165 : : we are encoding or decoding. When we are encoding we can immediately
166 : : use the data in the buffer; if not, we have to decode the data before
167 : : using it. */
168 : 404 : size_t need_offset = 0;
169 : 404 : GElf_Verneed *ndest;
170 : 404 : GElf_Verneed *nsrc;
171 : :
172 : : /* We rely on the types being all the same size. */
173 : 404 : eu_static_assert (sizeof (GElf_Verneed) == sizeof (Elf32_Verneed));
174 : 404 : eu_static_assert (sizeof (GElf_Vernaux) == sizeof (Elf32_Vernaux));
175 : 404 : eu_static_assert (sizeof (GElf_Verneed) == sizeof (Elf64_Verneed));
176 : 404 : eu_static_assert (sizeof (GElf_Vernaux) == sizeof (Elf64_Vernaux));
177 : :
178 [ + - ]: 404 : if (len == 0)
179 : : return;
180 : :
181 : : /* Below we rely on the next field offsets to be correct, start by
182 : : copying over all data as is in case some data isn't translated.
183 : : We don't want to leave (undefined) garbage in the dest buffer. */
184 : 404 : memmove (dest, src, len);
185 : :
186 : 416 : do
187 : : {
188 : 416 : size_t aux_offset;
189 : 416 : GElf_Vernaux *asrc;
190 : :
191 : : /* Test for correct offset. */
192 [ + - ]: 416 : if (need_offset > len
193 [ + - ]: 416 : || len - need_offset < sizeof (GElf_Verneed)
194 [ + - ]: 416 : || (need_offset & (__alignof__ (GElf_Verneed) - 1)) != 0)
195 : : return;
196 : :
197 : : /* Work the tree from the first record. */
198 : 416 : ndest = (GElf_Verneed *) ((char *) dest + need_offset);
199 : 416 : nsrc = (GElf_Verneed *) ((char *) src + need_offset);
200 : :
201 : : /* Decode first if necessary. */
202 [ + + ]: 416 : if (! encode)
203 : : {
204 [ + - ]: 306 : ndest->vn_version = bswap_16 (nsrc->vn_version);
205 : 306 : ndest->vn_cnt = bswap_16 (nsrc->vn_cnt);
206 [ + - ]: 306 : ndest->vn_file = bswap_32 (nsrc->vn_file);
207 : 306 : ndest->vn_aux = bswap_32 (nsrc->vn_aux);
208 : 306 : ndest->vn_next = bswap_32 (nsrc->vn_next);
209 : :
210 [ + - ]: 306 : if (ndest->vn_aux > len - need_offset)
211 : : return;
212 : 306 : aux_offset = need_offset + ndest->vn_aux;
213 : : }
214 : : else
215 : : {
216 [ + - ]: 110 : if (nsrc->vn_aux > len - need_offset)
217 : : return;
218 : 110 : aux_offset = need_offset + nsrc->vn_aux;
219 : : }
220 : :
221 : : /* Handle all the auxiliary records belonging to this requirement. */
222 : 460 : do
223 : : {
224 : 460 : GElf_Vernaux *adest;
225 : :
226 : : /* Test for correct offset. */
227 [ + - ]: 460 : if (aux_offset > len
228 [ + - ]: 460 : || len - aux_offset < sizeof (GElf_Vernaux)
229 [ + - ]: 460 : || (aux_offset & (__alignof__ (GElf_Vernaux) - 1)) != 0)
230 : : return;
231 : :
232 : 460 : adest = (GElf_Vernaux *) ((char *) dest + aux_offset);
233 : 460 : asrc = (GElf_Vernaux *) ((char *) src + aux_offset);
234 : :
235 [ + + ]: 460 : if (encode)
236 : : {
237 [ + - ]: 120 : if (asrc->vna_next > len - aux_offset)
238 : : return;
239 : 120 : aux_offset += asrc->vna_next;
240 : : }
241 : :
242 [ + + ]: 460 : adest->vna_hash = bswap_32 (asrc->vna_hash);
243 [ + + ]: 460 : adest->vna_flags = bswap_16 (asrc->vna_flags);
244 : 460 : adest->vna_other = bswap_16 (asrc->vna_other);
245 : 460 : adest->vna_name = bswap_32 (asrc->vna_name);
246 : 460 : adest->vna_next = bswap_32 (asrc->vna_next);
247 : :
248 [ + + ]: 460 : if (! encode)
249 : : {
250 [ + - ]: 340 : if (adest->vna_next > len - aux_offset)
251 : : return;
252 : 340 : aux_offset += adest->vna_next;
253 : : }
254 : : }
255 [ + + ]: 460 : while (asrc->vna_next != 0);
256 : :
257 : : /* Encode now if necessary. */
258 [ + + ]: 416 : if (encode)
259 : : {
260 [ + - ]: 110 : if (nsrc->vn_next > len - need_offset)
261 : : return;
262 : 110 : need_offset += nsrc->vn_next;
263 : :
264 : 110 : ndest->vn_version = bswap_16 (nsrc->vn_version);
265 : 110 : ndest->vn_cnt = bswap_16 (nsrc->vn_cnt);
266 : 110 : ndest->vn_file = bswap_32 (nsrc->vn_file);
267 : 110 : ndest->vn_aux = bswap_32 (nsrc->vn_aux);
268 : 110 : ndest->vn_next = bswap_32 (nsrc->vn_next);
269 : : }
270 : : else
271 : : {
272 [ + - ]: 306 : if (ndest->vn_next > len - need_offset)
273 : : return;
274 : 306 : need_offset += ndest->vn_next;
275 : : }
276 : : }
277 [ + + ]: 416 : while (nsrc->vn_next != 0);
278 : : }
|