Currently gelf_getmove does not distinguish between ELFCLASS32 and
ELFCLASS64 binaries.  This is assumes that Elf32_Move and Elf64_Move
structs are the same size.

This assumption is false since the m_info and m_poffset fields have
type uint32_t for Elf32_Move but uint64_t for Elf64_Move.

Fix this by handling ELFCLASS32 and ELFCLASS64 cases separately when
copying Elfxx_Move fields to dst.

Signed-off-by: Aaron Merey <[email protected]>
---
 libelf/gelf_getmove.c | 49 +++++++++++++++++++++++++++++++------------
 1 file changed, 36 insertions(+), 13 deletions(-)

diff --git a/libelf/gelf_getmove.c b/libelf/gelf_getmove.c
index 18efedcc..20fb54d5 100644
--- a/libelf/gelf_getmove.c
+++ b/libelf/gelf_getmove.c
@@ -53,27 +53,50 @@ gelf_getmove (Elf_Data *data, int ndx, GElf_Move *dst)
       return NULL;
     }
 
-  /* The types for 32 and 64 bit are the same.  Lucky us.  */
-  assert (sizeof (GElf_Move) == sizeof (Elf32_Move));
-  assert (sizeof (GElf_Move) == sizeof (Elf64_Move));
+  elf = ((Elf_Data_Scn *) data)->s->elf;
+  rwlock_rdlock (elf->lock);
 
-  /* The data is already in the correct form.  Just make sure the
-     index is OK.  */
-  if (INVALID_NDX (ndx, GElf_Move, data))
+  if (elf->class == ELFCLASS32)
     {
-      __libelf_seterrno (ELF_E_INVALID_INDEX);
-      goto out;
+      Elf32_Move *src;
+
+      if (INVALID_NDX (ndx, Elf32_Move, data))
+       {
+         __libelf_seterrno (ELF_E_INVALID_INDEX);
+         goto out;
+       }
+
+      src = &((Elf32_Move *) data->d_buf)[ndx];
+
+      /* The following copies may perform zero-extension. m_info can be
+        copied directly since ELF32_M_* and ELF64_M_* are the same.  */
+#define COPY(name) \
+      dst->name = src->name
+      COPY (m_value);
+      COPY (m_info);
+      COPY (m_poffset);
+      COPY (m_repeat);
+      COPY (m_stride);
     }
+  else
+    {
+      eu_static_assert (sizeof (GElf_Move) == sizeof (Elf64_Move));
 
-  elf = ((Elf_Data_Scn *) data)->s->elf;
-  rwlock_rdlock (elf->lock);
-
-  *dst = ((GElf_Move *) data->d_buf)[ndx];
+      /* The data is already in the correct form.  Just make sure the
+        index is OK.  */
+      if (INVALID_NDX (ndx, GElf_Move, data))
+       {
+         __libelf_seterrno (ELF_E_INVALID_INDEX);
+         goto out;
+       }
 
-  rwlock_unlock (elf->lock);
+      *dst = ((GElf_Move *) data->d_buf)[ndx];
+    }
 
   result = dst;
 
  out:
+  rwlock_unlock (elf->lock);
+
   return result;
 }
-- 
2.52.0

Reply via email to