Coverage Report

Created: 2025-04-11 06:16

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