summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmar Sandoval <osandov@fb.com>2020-03-18 13:18:51 -0700
committerMark Wielaard <mark@klomp.org>2020-03-23 11:23:24 +0100
commitee2dd07f57a43e1802461a65248438257ea94e58 (patch)
tree5d15d9be5853f53dd29ffea8dd896de903aff39c
parent5d67e9d3eaa6442b781cd6d8ce38a53b17136d12 (diff)
downloadelfutils-ee2dd07f57a43e1802461a65248438257ea94e58.tar.gz
libelf: handle PN_XNUM in elf_getphdrnum before shdr 0 is cached
__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>
-rw-r--r--libelf/ChangeLog5
-rw-r--r--libelf/elf_getphdrnum.c20
2 files changed, 19 insertions, 6 deletions
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 482ef32a..8f79a625 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-03-20 Matthias Maennich <maennich@google.com>
* elf_compress.c (__libelf_compress): Always call deflate_cleanup
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;
+ }
}
}