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