aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2018-03-28 21:27:48 +0200
committerMark Wielaard <mark@klomp.org>2018-03-30 22:42:44 +0200
commit560145d2b49347e92f4a265c3c3dbcae164ed9df (patch)
tree0cd9c9a516ffd914aab864933723276e9df5aace /src
parentafffdff29228db03e2131af577f58a22aec6c1fe (diff)
downloadelfutils-560145d2b49347e92f4a265c3c3dbcae164ed9df.tar.gz
readelf: Break sysv[64] symbol hash bucket chain loops.
The bucket chain should not contain loops. If it does we should mark the hash bucket chain as invalid. This is easily checked by noticing when we have seen more than the number of chain elements. Which equals the max number as symbols in the table. https://sourceware.org/bugzilla/show_bug.cgi?id=23011 Signed-off-by: Mark Wielaard <mark@klomp.org>
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog6
-rw-r--r--src/readelf.c8
2 files changed, 14 insertions, 0 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 1ad6b3db..e8bd6bf1 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,9 @@
+2018-03-28 Mark Wielaard <mark@klomp.org>
+
+ * readelf.c (handle_sysv_hash): Break bucket chain after nchain
+ entries are found.
+ (handle_sysv_hash64): Likewise.
+
2018-03-27 Mark Wielaard <mark@klomp.org>
* readelf.c (attr_callback): Print dwarf_dieoffset as %PRIx64,
diff --git a/src/readelf.c b/src/readelf.c
index 4e35b612..226b19be 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -3141,9 +3141,13 @@ handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
{
Elf32_Word inner = bucket[cnt];
+ Elf32_Word chain_len = 0;
while (inner > 0 && inner < nchain)
{
++nsyms;
+ ++chain_len;
+ if (chain_len > nchain)
+ goto invalid_data;
if (maxlength < ++lengths[cnt])
++maxlength;
@@ -3198,9 +3202,13 @@ handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
{
Elf64_Xword inner = bucket[cnt];
+ Elf64_Xword chain_len = 0;
while (inner > 0 && inner < nchain)
{
++nsyms;
+ ++chain_len;
+ if (chain_len > nchain)
+ goto invalid_data;
if (maxlength < ++lengths[cnt])
++maxlength;