Hi Anton,

On Thu, Feb 27, 2025 at 10:02:19PM +0100, Mark Wielaard wrote:
> On Thu, Feb 13, 2025 at 07:52:00PM +0300, Anton Moryakov wrote:
> > Static analyzer reported:
> > Return value of a function 'gelf_getehdr' is dereferenced at readelf.c:12443
> > without checking for NULL, but it is usually checked for this function 
> > (53/54).
> 
> I can see how a static analyzer thinks this gelf_getehdr call can
> fail. But it really cannot in this case. The core Elf was already
> checked for ehdr->type == ET_CORE in one of the callers. Or we
> wouldn't have gotten here.
> 
> What you could do to help the analyzer, and make this code slightly
> cleaner, is pass down that ehdr from handle_notes through the various
> handle_* functions.

I implemented this and puhsed it as attached.

Cheers,

Mark
>From 56e7a862d82e646bae79706343afa5f7800e2be1 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <m...@klomp.org>
Date: Tue, 29 Apr 2025 23:19:47 +0200
Subject: [PATCH 2/3] readelf: Pass around GElf_Ehdr instead of calling
 gelf_getehdr

handle_core_item calls gelf_getehdr for each item without checking if
the call succeeds. It should always succeed because process_elf_file
already checked gelf_getehdr returned a valid Ehdr before passing it
to handle_notes. Just pass the Ehdr down a couple more function calls.

        * readelf.c (handle_core_item): Take const Gelf_Ehdr and use it.
        (handle_core_items): Take const Gelf_Ehdr and pass it to
        handle_core_item.
        (handle_core_note): Take const Gelf_Ehdr and pass it to
        handle_core_items.
        (handle_notes_data): Pass ehdr to handle_core_note.

Signed-off-by: Mark Wielaard <m...@klomp.org>
---
 src/readelf.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/readelf.c b/src/readelf.c
index 5b0e7b474064..8603b3c441a1 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -12322,7 +12322,8 @@ convert (Elf *core, Elf_Type type, uint_fast16_t count,
 typedef uint8_t GElf_Byte;
 
 static unsigned int
-handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
+handle_core_item (Elf *core, const GElf_Ehdr *ehdr,
+                 const Ebl_Core_Item *item, const void *desc,
                  unsigned int colno, size_t *repeated_size)
 {
   uint_fast16_t count = item->count ?: 1;
@@ -12501,8 +12502,6 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, 
const void *desc,
             high half is the padding; it's presumably zero, but should
             be ignored anyway.  For big-endian, it means the 32-bit
             field went into the high half of USEC.  */
-         GElf_Ehdr ehdr_mem;
-         GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
          if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
            usec >>= 32;
          else
@@ -12594,7 +12593,8 @@ compare_core_item_groups (const void *a, const void *b)
 }
 
 static unsigned int
-handle_core_items (Elf *core, const void *desc, size_t descsz,
+handle_core_items (Elf *core, const GElf_Ehdr *ehdr,
+                  const void *desc, size_t descsz,
                   const Ebl_Core_Item *items, size_t nitems)
 {
   if (nitems == 0)
@@ -12610,7 +12610,7 @@ handle_core_items (Elf *core, const void *desc, size_t 
descsz,
     {
       assert (items[0].offset == 0);
       size_t size = descsz;
-      colno = handle_core_item (core, items, desc, colno, &size);
+      colno = handle_core_item (core, ehdr, items, desc, colno, &size);
       /* If SIZE is not zero here there is some remaining data.  But we do not
         know how to process it anyway.  */
       return colno;
@@ -12645,7 +12645,7 @@ handle_core_items (Elf *core, const void *desc, size_t 
descsz,
                && ((*item)->group == groups[i][0]->group
                    || !strcmp ((*item)->group, groups[i][0]->group)));
               ++item)
-           colno = handle_core_item (core, *item, desc, colno, NULL);
+           colno = handle_core_item (core, ehdr, *item, desc, colno, NULL);
 
          /* Force a line break at the end of the group.  */
          colno = WRAP_COLUMN;
@@ -13146,7 +13146,7 @@ handle_file_note (Elf *core, GElf_Word descsz, GElf_Off 
desc_pos)
 }
 
 static void
-handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
+handle_core_note (Ebl *ebl, const GElf_Ehdr *ehdr,  const GElf_Nhdr *nhdr,
                  const char *name, const void *desc)
 {
   GElf_Word regs_offset;
@@ -13163,7 +13163,7 @@ handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
      so that the ITEMS array does not describe the whole thing.
      For non-register notes, the actual descsz might be a multiple
      of the unit size, not just exactly the unit size.  */
-  unsigned int colno = handle_core_items (ebl->elf, desc,
+  unsigned int colno = handle_core_items (ebl->elf, ehdr, desc,
                                          nregloc == 0 ? nhdr->n_descsz : 0,
                                          items, nitems);
   if (colno != 0)
@@ -13243,10 +13243,10 @@ handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
                    break;
 
                  default:
-                   handle_core_note (ebl, &nhdr, name, desc);
+                   handle_core_note (ebl, ehdr, &nhdr, name, desc);
                  }
              else
-               handle_core_note (ebl, &nhdr, name, desc);
+               handle_core_note (ebl, ehdr, &nhdr, name, desc);
            }
          else
            ebl_object_note (ebl, nhdr.n_namesz, name, nhdr.n_type,
-- 
2.49.0

Reply via email to