Coverage Report

Created: 2026-08-13 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/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 <gelf.h>
32
33
#include "libelfP.h"
34
35
36
static void
37
elf_cvt_Verdef (void *dest, const void *src, size_t len, int encode)
38
2.64k
{
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
2.64k
  size_t def_offset = 0;
46
2.64k
  GElf_Verdef *ddest;
47
2.64k
  GElf_Verdef *dsrc;
48
49
  /* We rely on the types being all the same size.  */
50
2.64k
  eu_static_assert (sizeof (GElf_Verdef) == sizeof (Elf32_Verdef));
51
2.64k
  eu_static_assert (sizeof (GElf_Verdaux) == sizeof (Elf32_Verdaux));
52
2.64k
  eu_static_assert (sizeof (GElf_Verdef) == sizeof (Elf64_Verdef));
53
2.64k
  eu_static_assert (sizeof (GElf_Verdaux) == sizeof (Elf64_Verdaux));
54
55
2.64k
  if (len == 0)
56
0
    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
2.64k
  memmove (dest, src, len);
62
63
2.64k
  do
64
4.32k
    {
65
4.32k
      size_t aux_offset;
66
4.32k
      GElf_Verdaux *asrc;
67
68
      /* Test for correct offset.  */
69
4.32k
      if (def_offset > len
70
4.32k
    || len - def_offset < sizeof (GElf_Verdef)
71
4.23k
    || (def_offset & (__alignof__ (GElf_Verdef) - 1)) != 0)
72
349
  return;
73
74
      /* Work the tree from the first record.  */
75
3.97k
      ddest = (GElf_Verdef *) ((char *) dest + def_offset);
76
3.97k
      dsrc = (GElf_Verdef *) ((char *) src + def_offset);
77
78
      /* Decode first if necessary.  */
79
3.97k
      if (! encode)
80
3.97k
  {
81
3.97k
    ddest->vd_version = bswap_16 (dsrc->vd_version);
82
3.97k
    ddest->vd_flags = bswap_16 (dsrc->vd_flags);
83
3.97k
    ddest->vd_ndx = bswap_16 (dsrc->vd_ndx);
84
3.97k
    ddest->vd_cnt = bswap_16 (dsrc->vd_cnt);
85
3.97k
    ddest->vd_hash = bswap_32 (dsrc->vd_hash);
86
3.97k
    ddest->vd_aux = bswap_32 (dsrc->vd_aux);
87
3.97k
    ddest->vd_next = bswap_32 (dsrc->vd_next);
88
89
3.97k
    if (ddest->vd_aux > len - def_offset)
90
429
      return;
91
3.54k
    aux_offset = def_offset + ddest->vd_aux;
92
3.54k
  }
93
0
      else
94
0
  {
95
0
    if (dsrc->vd_aux > len - def_offset)
96
0
      return;
97
0
    aux_offset = def_offset + dsrc->vd_aux;
98
0
  }
99
100
      /* Handle all the auxiliary records belonging to this definition.  */
101
3.54k
      do
102
72.3k
  {
103
72.3k
    GElf_Verdaux *adest;
104
105
    /* Test for correct offset.  */
106
72.3k
    if (aux_offset > len
107
72.3k
        || len - aux_offset < sizeof (GElf_Verdaux)
108
72.2k
        || (aux_offset & (__alignof__ (GElf_Verdaux) - 1)) != 0)
109
400
      return;
110
111
71.9k
    adest = (GElf_Verdaux *) ((char *) dest + aux_offset);
112
71.9k
    asrc = (GElf_Verdaux *) ((char *) src + aux_offset);
113
114
71.9k
    if (encode)
115
0
      {
116
0
        if (asrc->vda_next > len - aux_offset)
117
0
    return;
118
0
        aux_offset += asrc->vda_next;
119
0
      }
120
121
71.9k
    adest->vda_name = bswap_32 (asrc->vda_name);
122
71.9k
    adest->vda_next = bswap_32 (asrc->vda_next);
123
124
71.9k
    if (! encode)
125
71.9k
      {
126
71.9k
        if (adest->vda_next > len - aux_offset)
127
495
    return;
128
71.4k
        aux_offset += adest->vda_next;
129
71.4k
      }
130
71.9k
  }
131
71.4k
      while (asrc->vda_next != 0);
132
133
      /* Encode now if necessary.  */
134
2.65k
      if (encode)
135
0
  {
136
0
    if (dsrc->vd_next > len - def_offset)
137
0
      return;
138
0
    def_offset += dsrc->vd_next;
139
140
0
    ddest->vd_version = bswap_16 (dsrc->vd_version);
141
0
    ddest->vd_flags = bswap_16 (dsrc->vd_flags);
142
0
    ddest->vd_ndx = bswap_16 (dsrc->vd_ndx);
143
0
    ddest->vd_cnt = bswap_16 (dsrc->vd_cnt);
144
0
    ddest->vd_hash = bswap_32 (dsrc->vd_hash);
145
0
    ddest->vd_aux = bswap_32 (dsrc->vd_aux);
146
0
    ddest->vd_next = bswap_32 (dsrc->vd_next);
147
0
  }
148
2.65k
      else
149
2.65k
  {
150
2.65k
    if (ddest->vd_next > len - def_offset)
151
394
      return;
152
2.26k
    def_offset += ddest->vd_next;
153
2.26k
  }
154
2.65k
    }
155
2.64k
  while (dsrc->vd_next != 0);
156
2.64k
}
157
158
159
static void
160
elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
161
3.13k
{
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
3.13k
  size_t need_offset = 0;
169
3.13k
  GElf_Verneed *ndest;
170
3.13k
  GElf_Verneed *nsrc;
171
172
  /* We rely on the types being all the same size.  */
173
3.13k
  eu_static_assert (sizeof (GElf_Verneed) == sizeof (Elf32_Verneed));
174
3.13k
  eu_static_assert (sizeof (GElf_Vernaux) == sizeof (Elf32_Vernaux));
175
3.13k
  eu_static_assert (sizeof (GElf_Verneed) == sizeof (Elf64_Verneed));
176
3.13k
  eu_static_assert (sizeof (GElf_Vernaux) == sizeof (Elf64_Vernaux));
177
178
3.13k
  if (len == 0)
179
0
    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
3.13k
  memmove (dest, src, len);
185
186
3.13k
  do
187
4.71k
    {
188
4.71k
      size_t aux_offset;
189
4.71k
      GElf_Vernaux *asrc;
190
191
      /* Test for correct offset.  */
192
4.71k
      if (need_offset > len
193
4.71k
    || len - need_offset < sizeof (GElf_Verneed)
194
4.46k
    || (need_offset & (__alignof__ (GElf_Verneed) - 1)) != 0)
195
495
  return;
196
197
      /* Work the tree from the first record.  */
198
4.21k
      ndest = (GElf_Verneed *) ((char *) dest + need_offset);
199
4.21k
      nsrc = (GElf_Verneed *) ((char *) src + need_offset);
200
201
      /* Decode first if necessary.  */
202
4.21k
      if (! encode)
203
4.21k
  {
204
4.21k
    ndest->vn_version = bswap_16 (nsrc->vn_version);
205
4.21k
    ndest->vn_cnt = bswap_16 (nsrc->vn_cnt);
206
4.21k
    ndest->vn_file = bswap_32 (nsrc->vn_file);
207
4.21k
    ndest->vn_aux = bswap_32 (nsrc->vn_aux);
208
4.21k
    ndest->vn_next = bswap_32 (nsrc->vn_next);
209
210
4.21k
    if (ndest->vn_aux > len - need_offset)
211
1.05k
      return;
212
3.15k
    aux_offset = need_offset + ndest->vn_aux;
213
3.15k
  }
214
0
      else
215
0
  {
216
0
    if (nsrc->vn_aux > len - need_offset)
217
0
      return;
218
0
    aux_offset = need_offset + nsrc->vn_aux;
219
0
  }
220
221
      /* Handle all the auxiliary records belonging to this requirement.  */
222
3.15k
      do
223
68.9k
  {
224
68.9k
    GElf_Vernaux *adest;
225
226
    /* Test for correct offset.  */
227
68.9k
    if (aux_offset > len
228
68.9k
        || len - aux_offset < sizeof (GElf_Vernaux)
229
68.7k
        || (aux_offset & (__alignof__ (GElf_Vernaux) - 1)) != 0)
230
535
      return;
231
232
68.4k
    adest = (GElf_Vernaux *) ((char *) dest + aux_offset);
233
68.4k
    asrc = (GElf_Vernaux *) ((char *) src + aux_offset);
234
235
68.4k
    if (encode)
236
0
      {
237
0
        if (asrc->vna_next > len - aux_offset)
238
0
    return;
239
0
        aux_offset += asrc->vna_next;
240
0
      }
241
242
68.4k
    adest->vna_hash = bswap_32 (asrc->vna_hash);
243
68.4k
    adest->vna_flags = bswap_16 (asrc->vna_flags);
244
68.4k
    adest->vna_other = bswap_16 (asrc->vna_other);
245
68.4k
    adest->vna_name = bswap_32 (asrc->vna_name);
246
68.4k
    adest->vna_next = bswap_32 (asrc->vna_next);
247
248
68.4k
    if (! encode)
249
68.4k
      {
250
68.4k
        if (adest->vna_next > len - aux_offset)
251
402
    return;
252
68.0k
        aux_offset += adest->vna_next;
253
68.0k
      }
254
68.4k
  }
255
68.0k
      while (asrc->vna_next != 0);
256
257
      /* Encode now if necessary.  */
258
2.22k
      if (encode)
259
0
  {
260
0
    if (nsrc->vn_next > len - need_offset)
261
0
      return;
262
0
    need_offset += nsrc->vn_next;
263
264
0
    ndest->vn_version = bswap_16 (nsrc->vn_version);
265
0
    ndest->vn_cnt = bswap_16 (nsrc->vn_cnt);
266
0
    ndest->vn_file = bswap_32 (nsrc->vn_file);
267
0
    ndest->vn_aux = bswap_32 (nsrc->vn_aux);
268
0
    ndest->vn_next = bswap_32 (nsrc->vn_next);
269
0
  }
270
2.22k
      else
271
2.22k
  {
272
2.22k
    if (ndest->vn_next > len - need_offset)
273
280
      return;
274
1.94k
    need_offset += ndest->vn_next;
275
1.94k
  }
276
2.22k
    }
277
3.13k
  while (nsrc->vn_next != 0);
278
3.13k
}