]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libelf: handle PN_XNUM in elf_getphdrnum before shdr 0 is cached
authorOmar Sandoval <osandov@fb.com>
Wed, 18 Mar 2020 20:18:51 +0000 (13:18 -0700)
committerMark Wielaard <mark@klomp.org>
Mon, 23 Mar 2020 10:23:24 +0000 (11:23 +0100)
__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
libelf/elf_getphdrnum.c

index 482ef32a3cc1d13faf97c49dd53b83ed71d91c4c..8f79a6252b61fac79442813bb28fa415797001c7 100644 (file)
@@ -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-03-20  Matthias Maennich  <maennich@google.com>
 
        * elf_compress.c (__libelf_compress): Always call deflate_cleanup
index f91cba981a1f45313bf5fe23fcde738992d16a7b..53617dfc7f61383b98525fbeb12501dcc95d415a 100644 (file)
@@ -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;
+          }
        }
    }