Coverage Report

Created: 2025-07-11 06:46

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