Coverage Report

Created: 2025-08-24 06:03

/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
483
{
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
483
  size_t def_offset = 0;
47
483
  GElf_Verdef *ddest;
48
483
  GElf_Verdef *dsrc;
49
50
  /* We rely on the types being all the same size.  */
51
483
  assert (sizeof (GElf_Verdef) == sizeof (Elf32_Verdef));
52
483
  assert (sizeof (GElf_Verdaux) == sizeof (Elf32_Verdaux));
53
483
  assert (sizeof (GElf_Verdef) == sizeof (Elf64_Verdef));
54
483
  assert (sizeof (GElf_Verdaux) == sizeof (Elf64_Verdaux));
55
56
483
  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
483
  memmove (dest, src, len);
63
64
483
  do
65
882
    {
66
882
      size_t aux_offset;
67
882
      GElf_Verdaux *asrc;
68
69
      /* Test for correct offset.  */
70
882
      if (def_offset > len
71
882
    || len - def_offset < sizeof (GElf_Verdef)
72
882
    || (def_offset & (__alignof__ (GElf_Verdef) - 1)) != 0)
73
111
  return;
74
75
      /* Work the tree from the first record.  */
76
771
      ddest = (GElf_Verdef *) ((char *) dest + def_offset);
77
771
      dsrc = (GElf_Verdef *) ((char *) src + def_offset);
78
79
      /* Decode first if necessary.  */
80
771
      if (! encode)
81
771
  {
82
771
    ddest->vd_version = bswap_16 (dsrc->vd_version);
83
771
    ddest->vd_flags = bswap_16 (dsrc->vd_flags);
84
771
    ddest->vd_ndx = bswap_16 (dsrc->vd_ndx);
85
771
    ddest->vd_cnt = bswap_16 (dsrc->vd_cnt);
86
771
    ddest->vd_hash = bswap_32 (dsrc->vd_hash);
87
771
    ddest->vd_aux = bswap_32 (dsrc->vd_aux);
88
771
    ddest->vd_next = bswap_32 (dsrc->vd_next);
89
90
771
    if (ddest->vd_aux > len - def_offset)
91
82
      return;
92
689
    aux_offset = def_offset + ddest->vd_aux;
93
689
  }
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
689
      do
103
3.46k
  {
104
3.46k
    GElf_Verdaux *adest;
105
106
    /* Test for correct offset.  */
107
3.46k
    if (aux_offset > len
108
3.46k
        || len - aux_offset < sizeof (GElf_Verdaux)
109
3.46k
        || (aux_offset & (__alignof__ (GElf_Verdaux) - 1)) != 0)
110
95
      return;
111
112
3.37k
    adest = (GElf_Verdaux *) ((char *) dest + aux_offset);
113
3.37k
    asrc = (GElf_Verdaux *) ((char *) src + aux_offset);
114
115
3.37k
    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
3.37k
    adest->vda_name = bswap_32 (asrc->vda_name);
123
3.37k
    adest->vda_next = bswap_32 (asrc->vda_next);
124
125
3.37k
    if (! encode)
126
3.37k
      {
127
3.37k
        if (adest->vda_next > len - aux_offset)
128
65
    return;
129
3.30k
        aux_offset += adest->vda_next;
130
3.30k
      }
131
3.37k
  }
132
3.30k
      while (asrc->vda_next != 0);
133
134
      /* Encode now if necessary.  */
135
529
      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
529
      else
150
529
  {
151
529
    if (ddest->vd_next > len - def_offset)
152
73
      return;
153
456
    def_offset += ddest->vd_next;
154
456
  }
155
529
    }
156
483
  while (dsrc->vd_next != 0);
157
483
}
158
159
160
static void
161
elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
162
733
{
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
733
  size_t need_offset = 0;
170
733
  GElf_Verneed *ndest;
171
733
  GElf_Verneed *nsrc;
172
173
  /* We rely on the types being all the same size.  */
174
733
  assert (sizeof (GElf_Verneed) == sizeof (Elf32_Verneed));
175
733
  assert (sizeof (GElf_Vernaux) == sizeof (Elf32_Vernaux));
176
733
  assert (sizeof (GElf_Verneed) == sizeof (Elf64_Verneed));
177
733
  assert (sizeof (GElf_Vernaux) == sizeof (Elf64_Vernaux));
178
179
733
  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
733
  memmove (dest, src, len);
186
187
733
  do
188
1.07k
    {
189
1.07k
      size_t aux_offset;
190
1.07k
      GElf_Vernaux *asrc;
191
192
      /* Test for correct offset.  */
193
1.07k
      if (need_offset > len
194
1.07k
    || len - need_offset < sizeof (GElf_Verneed)
195
1.07k
    || (need_offset & (__alignof__ (GElf_Verneed) - 1)) != 0)
196
87
  return;
197
198
      /* Work the tree from the first record.  */
199
988
      ndest = (GElf_Verneed *) ((char *) dest + need_offset);
200
988
      nsrc = (GElf_Verneed *) ((char *) src + need_offset);
201
202
      /* Decode first if necessary.  */
203
988
      if (! encode)
204
988
  {
205
988
    ndest->vn_version = bswap_16 (nsrc->vn_version);
206
988
    ndest->vn_cnt = bswap_16 (nsrc->vn_cnt);
207
988
    ndest->vn_file = bswap_32 (nsrc->vn_file);
208
988
    ndest->vn_aux = bswap_32 (nsrc->vn_aux);
209
988
    ndest->vn_next = bswap_32 (nsrc->vn_next);
210
211
988
    if (ndest->vn_aux > len - need_offset)
212
217
      return;
213
771
    aux_offset = need_offset + ndest->vn_aux;
214
771
  }
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
771
      do
224
2.47k
  {
225
2.47k
    GElf_Vernaux *adest;
226
227
    /* Test for correct offset.  */
228
2.47k
    if (aux_offset > len
229
2.47k
        || len - aux_offset < sizeof (GElf_Vernaux)
230
2.47k
        || (aux_offset & (__alignof__ (GElf_Vernaux) - 1)) != 0)
231
169
      return;
232
233
2.30k
    adest = (GElf_Vernaux *) ((char *) dest + aux_offset);
234
2.30k
    asrc = (GElf_Vernaux *) ((char *) src + aux_offset);
235
236
2.30k
    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
2.30k
    adest->vna_hash = bswap_32 (asrc->vna_hash);
244
2.30k
    adest->vna_flags = bswap_16 (asrc->vna_flags);
245
2.30k
    adest->vna_other = bswap_16 (asrc->vna_other);
246
2.30k
    adest->vna_name = bswap_32 (asrc->vna_name);
247
2.30k
    adest->vna_next = bswap_32 (asrc->vna_next);
248
249
2.30k
    if (! encode)
250
2.30k
      {
251
2.30k
        if (adest->vna_next > len - aux_offset)
252
94
    return;
253
2.21k
        aux_offset += adest->vna_next;
254
2.21k
      }
255
2.30k
  }
256
2.21k
      while (asrc->vna_next != 0);
257
258
      /* Encode now if necessary.  */
259
508
      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
508
      else
272
508
  {
273
508
    if (ndest->vn_next > len - need_offset)
274
76
      return;
275
432
    need_offset += ndest->vn_next;
276
432
  }
277
508
    }
278
733
  while (nsrc->vn_next != 0);
279
733
}