Coverage Report

Created: 2026-08-30 07:12

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