LCOV - code coverage report
Current view: top level - libelf - elf_strptr.c (source / functions) Hit Total Coverage
Test: elfutils-0.175 Lines: 53 65 81.5 %
Date: 2018-11-16 13:02:39 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Return string pointer from string section.
       2             :    Copyright (C) 1998-2002, 2004, 2008, 2009, 2015 Red Hat, Inc.
       3             :    This file is part of elfutils.
       4             :    Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
       5             : 
       6             :    This file is free software; you can redistribute it and/or modify
       7             :    it under the terms of either
       8             : 
       9             :      * the GNU Lesser General Public License as published by the Free
      10             :        Software Foundation; either version 3 of the License, or (at
      11             :        your option) any later version
      12             : 
      13             :    or
      14             : 
      15             :      * the GNU General Public License as published by the Free
      16             :        Software Foundation; either version 2 of the License, or (at
      17             :        your option) any later version
      18             : 
      19             :    or both in parallel, as here.
      20             : 
      21             :    elfutils is distributed in the hope that it will be useful, but
      22             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      23             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      24             :    General Public License for more details.
      25             : 
      26             :    You should have received copies of the GNU General Public License and
      27             :    the GNU Lesser General Public License along with this program.  If
      28             :    not, see <http://www.gnu.org/licenses/>.  */
      29             : 
      30             : #ifdef HAVE_CONFIG_H
      31             : # include <config.h>
      32             : #endif
      33             : 
      34             : #include <libelf.h>
      35             : #include <stdbool.h>
      36             : #include <stddef.h>
      37             : 
      38             : #include "libelfP.h"
      39             : 
      40             : 
      41             : static void *
      42           6 : get_zdata (Elf_Scn *strscn)
      43             : {
      44             :   size_t zsize, zalign;
      45           6 :   void *zdata = __libelf_decompress_elf (strscn, &zsize, &zalign);
      46           6 :   if (zdata == NULL)
      47             :     return NULL;
      48             : 
      49           6 :   strscn->zdata_base = zdata;
      50           6 :   strscn->zdata_size = zsize;
      51           6 :   strscn->zdata_align = zalign;
      52             : 
      53           6 :   return zdata;
      54             : }
      55             : 
      56             : static bool validate_str (const char *str, size_t from, size_t to)
      57             : {
      58             : #if HAVE_DECL_MEMRCHR
      59     6015163 :   return memrchr (&str[from], '\0', to - from) != NULL;
      60             : #else
      61             :   do {
      62             :     if (to <= from)
      63             :       return false;
      64             : 
      65             :     to--;
      66             :   } while (str[to]);
      67             : 
      68             :   return true;
      69             : #endif
      70             : }
      71             : 
      72             : char *
      73     6015174 : elf_strptr (Elf *elf, size_t idx, size_t offset)
      74             : {
      75     6015174 :   if (elf == NULL)
      76             :     return NULL;
      77             : 
      78     6015174 :   if (elf->kind != ELF_K_ELF)
      79             :     {
      80           0 :       __libelf_seterrno (ELF_E_INVALID_HANDLE);
      81           0 :       return NULL;
      82             :     }
      83             : 
      84             :   rwlock_rdlock (elf->lock);
      85             : 
      86     6015174 :   char *result = NULL;
      87             :   Elf_Scn *strscn;
      88             : 
      89             :   /* Find the section in the list.  */
      90     6015174 :   Elf_ScnList *runp = (elf->class == ELFCLASS32
      91             :                        || (offsetof (struct Elf, state.elf32.scns)
      92             :                            == offsetof (struct Elf, state.elf64.scns))
      93             :                        ? &elf->state.elf32.scns : &elf->state.elf64.scns);
      94             :   while (1)
      95             :     {
      96     6079725 :       if (idx < runp->max)
      97             :         {
      98     6015174 :           if (idx < runp->cnt)
      99     6015174 :             strscn = &runp->data[idx];
     100             :           else
     101             :             {
     102           0 :               __libelf_seterrno (ELF_E_INVALID_INDEX);
     103           0 :               goto out;
     104             :             }
     105             :           break;
     106             :         }
     107             : 
     108       64551 :       idx -= runp->max;
     109             : 
     110       64551 :       runp = runp->next;
     111       64551 :       if (runp == NULL)
     112             :         {
     113           0 :           __libelf_seterrno (ELF_E_INVALID_INDEX);
     114           0 :           goto out;
     115             :         }
     116             :     }
     117             : 
     118     6015174 :   size_t sh_size = 0;
     119     6015174 :   if (elf->class == ELFCLASS32)
     120             :     {
     121     2993747 :       Elf32_Shdr *shdr = strscn->shdr.e32 ?: __elf32_getshdr_rdlock (strscn);
     122     2993747 :       if (unlikely (shdr->sh_type != SHT_STRTAB))
     123             :         {
     124             :           /* This is no string section.  */
     125           5 :           __libelf_seterrno (ELF_E_INVALID_SECTION);
     126           5 :           goto out;
     127             :         }
     128             : 
     129     2993742 :       if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
     130     2993702 :         sh_size = shdr->sh_size;
     131             :       else
     132             :         {
     133          40 :           if (strscn->zdata_base == NULL && get_zdata (strscn) == NULL)
     134             :             goto out;
     135          40 :           sh_size = strscn->zdata_size;
     136             :         }
     137             : 
     138     2993742 :       if (unlikely (offset >= sh_size))
     139             :         {
     140             :           /* The given offset is too big, it is beyond this section.  */
     141           3 :           __libelf_seterrno (ELF_E_OFFSET_RANGE);
     142           3 :           goto out;
     143             :         }
     144             :     }
     145             :   else
     146             :     {
     147     3021427 :       Elf64_Shdr *shdr = strscn->shdr.e64 ?: __elf64_getshdr_rdlock (strscn);
     148     3021427 :       if (unlikely (shdr->sh_type != SHT_STRTAB))
     149             :         {
     150             :           /* This is no string section.  */
     151           0 :           __libelf_seterrno (ELF_E_INVALID_SECTION);
     152           0 :           goto out;
     153             :         }
     154             : 
     155     3021427 :       if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
     156     3021390 :         sh_size = shdr->sh_size;
     157             :       else
     158             :         {
     159          37 :           if (strscn->zdata_base == NULL && get_zdata (strscn) == NULL)
     160             :             goto out;
     161          37 :           sh_size = strscn->zdata_size;
     162             :         }
     163             : 
     164     3021427 :       if (unlikely (offset >= sh_size))
     165             :         {
     166             :           /* The given offset is too big, it is beyond this section.  */
     167           3 :           __libelf_seterrno (ELF_E_OFFSET_RANGE);
     168           3 :           goto out;
     169             :         }
     170             :     }
     171             : 
     172     6015163 :   if (strscn->rawdata_base == NULL && ! strscn->data_read)
     173             :     {
     174             :       rwlock_unlock (elf->lock);
     175             :       rwlock_wrlock (elf->lock);
     176             :       if (strscn->rawdata_base == NULL && ! strscn->data_read
     177             :         /* Read the section data.  */
     178        1522 :           && __libelf_set_rawdata_wrlock (strscn) != 0)
     179             :         goto out;
     180             :     }
     181             : 
     182     6015163 :   if (unlikely (strscn->zdata_base != NULL))
     183             :     {
     184             :       /* Make sure the string is NUL terminated.  Start from the end,
     185             :          which very likely is a NUL char.  */
     186       22698 :       if (likely (validate_str (strscn->zdata_base, offset, sh_size)))
     187             :         result = &strscn->zdata_base[offset];
     188             :       else
     189           0 :         __libelf_seterrno (ELF_E_INVALID_INDEX);
     190             :     }
     191     6003814 :   else if (likely (strscn->data_list_rear == NULL))
     192             :     {
     193             :       // XXX The above is currently correct since elf_newdata will
     194             :       // make sure to convert the rawdata into the datalist if
     195             :       // necessary. But it would be more efficient to keep the rawdata
     196             :       // unconverted and only then iterate over the rest of the (newly
     197             :       // added data) list.  Note that when the ELF file is mmapped
     198             :       // rawdata_base can be set while rawdata.d hasn't been
     199             :       // initialized yet (when data_read is zero). So we cannot just
     200             :       // look at the rawdata.d.d_size.
     201             : 
     202             :       /* Make sure the string is NUL terminated.  Start from the end,
     203             :          which very likely is a NUL char.  */
     204    11803498 :       if (likely (validate_str (strscn->rawdata_base, offset, sh_size)))
     205             :         result = &strscn->rawdata_base[offset];
     206             :       else
     207           0 :         __libelf_seterrno (ELF_E_INVALID_INDEX);
     208             :     }
     209             :   else
     210             :     {
     211             :       /* This is a file which is currently created.  Use the list of
     212             :          data blocks.  */
     213      102065 :       struct Elf_Data_List *dl = &strscn->data_list;
     214      204346 :       while (dl != NULL)
     215             :         {
     216      102281 :           if (offset >= (size_t) dl->data.d.d_off
     217      102281 :               && offset < dl->data.d.d_off + dl->data.d.d_size)
     218             :             {
     219             :               /* Make sure the string is NUL terminated.  Start from
     220             :                  the end, which very likely is a NUL char.  */
     221      204130 :               if (likely (validate_str ((char *) dl->data.d.d_buf,
     222             :                                         offset - dl->data.d.d_off,
     223             :                                         dl->data.d.d_size)))
     224             :                 result = ((char *) dl->data.d.d_buf
     225             :                           + (offset - dl->data.d.d_off));
     226             :               else
     227           0 :                 __libelf_seterrno (ELF_E_INVALID_INDEX);
     228             :               break;
     229             :             }
     230             : 
     231         216 :           dl = dl->next;
     232             :         }
     233             :     }
     234             : 
     235           0 :  out:
     236             :   rwlock_unlock (elf->lock);
     237             : 
     238             :   return result;
     239             : }
     240             : INTDEF(elf_strptr)

Generated by: LCOV version 1.13