Coverage Report

Created: 2025-11-13 06:36

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