Coverage Report

Created: 2026-03-10 06:19

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