Coverage Report

Created: 2025-08-26 06:08

/src/libbpf/elfutils/libelf/version_xlate.h
Line
Count
Source (jump to first uncovered line)
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 <assert.h>
32
#include <gelf.h>
33
34
#include "libelfP.h"
35
36
37
static void
38
elf_cvt_Verdef (void *dest, const void *src, size_t len, int encode)
39
513
{
40
  /* We have two different record types: ElfXX_Verndef and ElfXX_Verdaux.
41
     To recognize them we have to walk the data structure and convert
42
     them one after the other.  The ENCODE parameter specifies whether
43
     we are encoding or decoding.  When we are encoding we can immediately
44
     use the data in the buffer; if not, we have to decode the data before
45
     using it.  */
46
513
  size_t def_offset = 0;
47
513
  GElf_Verdef *ddest;
48
513
  GElf_Verdef *dsrc;
49
50
  /* We rely on the types being all the same size.  */
51
513
  assert (sizeof (GElf_Verdef) == sizeof (Elf32_Verdef));
52
513
  assert (sizeof (GElf_Verdaux) == sizeof (Elf32_Verdaux));
53
513
  assert (sizeof (GElf_Verdef) == sizeof (Elf64_Verdef));
54
513
  assert (sizeof (GElf_Verdaux) == sizeof (Elf64_Verdaux));
55
56
513
  if (len == 0)
57
0
    return;
58
59
  /* Below we rely on the next field offsets to be correct, start by
60
     copying over all data as is in case some data isn't translated.
61
     We don't want to leave (undefined) garbage in the dest buffer.  */
62
513
  memmove (dest, src, len);
63
64
513
  do
65
972
    {
66
972
      size_t aux_offset;
67
972
      GElf_Verdaux *asrc;
68
69
      /* Test for correct offset.  */
70
972
      if (def_offset > len
71
972
    || len - def_offset < sizeof (GElf_Verdef)
72
972
    || (def_offset & (__alignof__ (GElf_Verdef) - 1)) != 0)
73
94
  return;
74
75
      /* Work the tree from the first record.  */
76
878
      ddest = (GElf_Verdef *) ((char *) dest + def_offset);
77
878
      dsrc = (GElf_Verdef *) ((char *) src + def_offset);
78
79
      /* Decode first if necessary.  */
80
878
      if (! encode)
81
878
  {
82
878
    ddest->vd_version = bswap_16 (dsrc->vd_version);
83
878
    ddest->vd_flags = bswap_16 (dsrc->vd_flags);
84
878
    ddest->vd_ndx = bswap_16 (dsrc->vd_ndx);
85
878
    ddest->vd_cnt = bswap_16 (dsrc->vd_cnt);
86
878
    ddest->vd_hash = bswap_32 (dsrc->vd_hash);
87
878
    ddest->vd_aux = bswap_32 (dsrc->vd_aux);
88
878
    ddest->vd_next = bswap_32 (dsrc->vd_next);
89
90
878
    if (ddest->vd_aux > len - def_offset)
91
90
      return;
92
788
    aux_offset = def_offset + ddest->vd_aux;
93
788
  }
94
0
      else
95
0
  {
96
0
    if (dsrc->vd_aux > len - def_offset)
97
0
      return;
98
0
    aux_offset = def_offset + dsrc->vd_aux;
99
0
  }
100
101
      /* Handle all the auxiliary records belonging to this definition.  */
102
788
      do
103
4.36k
  {
104
4.36k
    GElf_Verdaux *adest;
105
106
    /* Test for correct offset.  */
107
4.36k
    if (aux_offset > len
108
4.36k
        || len - aux_offset < sizeof (GElf_Verdaux)
109
4.36k
        || (aux_offset & (__alignof__ (GElf_Verdaux) - 1)) != 0)
110
98
      return;
111
112
4.26k
    adest = (GElf_Verdaux *) ((char *) dest + aux_offset);
113
4.26k
    asrc = (GElf_Verdaux *) ((char *) src + aux_offset);
114
115
4.26k
    if (encode)
116
0
      {
117
0
        if (asrc->vda_next > len - aux_offset)
118
0
    return;
119
0
        aux_offset += asrc->vda_next;
120
0
      }
121
122
4.26k
    adest->vda_name = bswap_32 (asrc->vda_name);
123
4.26k
    adest->vda_next = bswap_32 (asrc->vda_next);
124
125
4.26k
    if (! encode)
126
4.26k
      {
127
4.26k
        if (adest->vda_next > len - aux_offset)
128
83
    return;
129
4.18k
        aux_offset += adest->vda_next;
130
4.18k
      }
131
4.26k
  }
132
4.18k
      while (asrc->vda_next != 0);
133
134
      /* Encode now if necessary.  */
135
607
      if (encode)
136
0
  {
137
0
    if (dsrc->vd_next > len - def_offset)
138
0
      return;
139
0
    def_offset += dsrc->vd_next;
140
141
0
    ddest->vd_version = bswap_16 (dsrc->vd_version);
142
0
    ddest->vd_flags = bswap_16 (dsrc->vd_flags);
143
0
    ddest->vd_ndx = bswap_16 (dsrc->vd_ndx);
144
0
    ddest->vd_cnt = bswap_16 (dsrc->vd_cnt);
145
0
    ddest->vd_hash = bswap_32 (dsrc->vd_hash);
146
0
    ddest->vd_aux = bswap_32 (dsrc->vd_aux);
147
0
    ddest->vd_next = bswap_32 (dsrc->vd_next);
148
0
  }
149
607
      else
150
607
  {
151
607
    if (ddest->vd_next > len - def_offset)
152
76
      return;
153
531
    def_offset += ddest->vd_next;
154
531
  }
155
607
    }
156
531
  while (dsrc->vd_next != 0);
157
513
}
158
159
160
static void
161
elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
162
887
{
163
  /* We have two different record types: ElfXX_Verndef and ElfXX_Verdaux.
164
     To recognize them we have to walk the data structure and convert
165
     them one after the other.  The ENCODE parameter specifies whether
166
     we are encoding or decoding.  When we are encoding we can immediately
167
     use the data in the buffer; if not, we have to decode the data before
168
     using it.  */
169
887
  size_t need_offset = 0;
170
887
  GElf_Verneed *ndest;
171
887
  GElf_Verneed *nsrc;
172
173
  /* We rely on the types being all the same size.  */
174
887
  assert (sizeof (GElf_Verneed) == sizeof (Elf32_Verneed));
175
887
  assert (sizeof (GElf_Vernaux) == sizeof (Elf32_Vernaux));
176
887
  assert (sizeof (GElf_Verneed) == sizeof (Elf64_Verneed));
177
887
  assert (sizeof (GElf_Vernaux) == sizeof (Elf64_Vernaux));
178
179
887
  if (len == 0)
180
0
    return;
181
182
  /* Below we rely on the next field offsets to be correct, start by
183
     copying over all data as is in case some data isn't translated.
184
     We don't want to leave (undefined) garbage in the dest buffer.  */
185
887
  memmove (dest, src, len);
186
187
887
  do
188
1.14k
    {
189
1.14k
      size_t aux_offset;
190
1.14k
      GElf_Vernaux *asrc;
191
192
      /* Test for correct offset.  */
193
1.14k
      if (need_offset > len
194
1.14k
    || len - need_offset < sizeof (GElf_Verneed)
195
1.14k
    || (need_offset & (__alignof__ (GElf_Verneed) - 1)) != 0)
196
103
  return;
197
198
      /* Work the tree from the first record.  */
199
1.03k
      ndest = (GElf_Verneed *) ((char *) dest + need_offset);
200
1.03k
      nsrc = (GElf_Verneed *) ((char *) src + need_offset);
201
202
      /* Decode first if necessary.  */
203
1.03k
      if (! encode)
204
1.03k
  {
205
1.03k
    ndest->vn_version = bswap_16 (nsrc->vn_version);
206
1.03k
    ndest->vn_cnt = bswap_16 (nsrc->vn_cnt);
207
1.03k
    ndest->vn_file = bswap_32 (nsrc->vn_file);
208
1.03k
    ndest->vn_aux = bswap_32 (nsrc->vn_aux);
209
1.03k
    ndest->vn_next = bswap_32 (nsrc->vn_next);
210
211
1.03k
    if (ndest->vn_aux > len - need_offset)
212
203
      return;
213
834
    aux_offset = need_offset + ndest->vn_aux;
214
834
  }
215
0
      else
216
0
  {
217
0
    if (nsrc->vn_aux > len - need_offset)
218
0
      return;
219
0
    aux_offset = need_offset + nsrc->vn_aux;
220
0
  }
221
222
      /* Handle all the auxiliary records belonging to this requirement.  */
223
834
      do
224
1.87k
  {
225
1.87k
    GElf_Vernaux *adest;
226
227
    /* Test for correct offset.  */
228
1.87k
    if (aux_offset > len
229
1.87k
        || len - aux_offset < sizeof (GElf_Vernaux)
230
1.87k
        || (aux_offset & (__alignof__ (GElf_Vernaux) - 1)) != 0)
231
229
      return;
232
233
1.64k
    adest = (GElf_Vernaux *) ((char *) dest + aux_offset);
234
1.64k
    asrc = (GElf_Vernaux *) ((char *) src + aux_offset);
235
236
1.64k
    if (encode)
237
0
      {
238
0
        if (asrc->vna_next > len - aux_offset)
239
0
    return;
240
0
        aux_offset += asrc->vna_next;
241
0
      }
242
243
1.64k
    adest->vna_hash = bswap_32 (asrc->vna_hash);
244
1.64k
    adest->vna_flags = bswap_16 (asrc->vna_flags);
245
1.64k
    adest->vna_other = bswap_16 (asrc->vna_other);
246
1.64k
    adest->vna_name = bswap_32 (asrc->vna_name);
247
1.64k
    adest->vna_next = bswap_32 (asrc->vna_next);
248
249
1.64k
    if (! encode)
250
1.64k
      {
251
1.64k
        if (adest->vna_next > len - aux_offset)
252
123
    return;
253
1.52k
        aux_offset += adest->vna_next;
254
1.52k
      }
255
1.64k
  }
256
1.52k
      while (asrc->vna_next != 0);
257
258
      /* Encode now if necessary.  */
259
482
      if (encode)
260
0
  {
261
0
    if (nsrc->vn_next > len - need_offset)
262
0
      return;
263
0
    need_offset += nsrc->vn_next;
264
265
0
    ndest->vn_version = bswap_16 (nsrc->vn_version);
266
0
    ndest->vn_cnt = bswap_16 (nsrc->vn_cnt);
267
0
    ndest->vn_file = bswap_32 (nsrc->vn_file);
268
0
    ndest->vn_aux = bswap_32 (nsrc->vn_aux);
269
0
    ndest->vn_next = bswap_32 (nsrc->vn_next);
270
0
  }
271
482
      else
272
482
  {
273
482
    if (ndest->vn_next > len - need_offset)
274
81
      return;
275
401
    need_offset += ndest->vn_next;
276
401
  }
277
482
    }
278
887
  while (nsrc->vn_next != 0);
279
887
}