[PATCH] libelf: handle PN_XNUM in elf_getphdrnum before shdr 0 is cached

Omar Sandoval osandov@osandov.com
Wed Mar 18 20:18:51 GMT 2020


From: Omar Sandoval <osandov@fb.com>

__elf_getphdrnum_rdlock() handles PN_XNUM by getting sh_info from
elf->state.elf{32,64}.scns.data[0].shdr.e{32,64}. However, that is only
a cache that may or may not have been populated by elf_begin() or
elf{32,64}_getshdr(); if it hasn't been cached yet, elf_getphdrnum()
returns 65535 (the value of PN_XNUM) instead. We should explicitly get
the shdr if it isn't cached.

Signed-off-by: Omar Sandoval <osandov@fb.com>
---
 libelf/ChangeLog        |  5 +++++
 libelf/elf_getphdrnum.c | 20 ++++++++++++++------
 2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index dde6c81d..03c94cce 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,8 @@
+2020-03-18  Omar Sandoval  <osandov@fb.com>
+
+	* elf_getphdrnum.c (__elf_getphdrnum_rdlock): Call
+	__elf{32,64}_getshdr_rdlock if the shdr is not cached.
+
 2019-06-18  Mark Wielaard  <mark@klomp.org>
 
 	* common.h (allocate_elf): Use int64_t instead of off_t for offset.
diff --git a/libelf/elf_getphdrnum.c b/libelf/elf_getphdrnum.c
index f91cba98..53617dfc 100644
--- a/libelf/elf_getphdrnum.c
+++ b/libelf/elf_getphdrnum.c
@@ -63,15 +63,23 @@ __elf_getphdrnum_rdlock (Elf *elf, size_t *dst)
 
      if (elf->class == ELFCLASS32)
        {
-	 if (likely (scns->cnt > 0
-		     && elf->state.elf32.scns.data[0].shdr.e32 != NULL))
-	   *dst = scns->data[0].shdr.e32->sh_info;
+	 if (likely (scns->cnt > 0))
+	   {
+	     Elf_Scn *scn = &elf->state.elf32.scns.data[0];
+	     Elf32_Shdr *shdr = scn->shdr.e32 ?: __elf32_getshdr_rdlock (scn);
+	     if (shdr)
+	       *dst = shdr->sh_info;
+	   }
        }
      else
        {
-	 if (likely (scns->cnt > 0
-		     && elf->state.elf64.scns.data[0].shdr.e64 != NULL))
-	   *dst = scns->data[0].shdr.e64->sh_info;
+	 if (likely (scns->cnt > 0))
+	   {
+	     Elf_Scn *scn = &elf->state.elf64.scns.data[0];
+	     Elf64_Shdr *shdr = scn->shdr.e64 ?: __elf64_getshdr_rdlock (scn);
+	     if (shdr)
+	       *dst = shdr->sh_info;
+	   }
        }
    }
 
-- 
2.25.1



More information about the Elfutils-devel mailing list