]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
gelf_update_move.c: Handle ELFCLASS32 and ELFCLASS64 separately
authorAaron Merey <amerey@redhat.com>
Fri, 13 Mar 2026 21:46:48 +0000 (17:46 -0400)
committerAaron Merey <amerey@redhat.com>
Fri, 13 Mar 2026 21:46:48 +0000 (17:46 -0400)
Similar to commit c460e2088, gelf_update_move does not distinguish
between ELFCLASS32 and ELFCLASS64 binaries.

The code assumes that Elf32_Move and Elf64_Move structs are the same
size but they are not. 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.

Signed-off-by: Aaron Merey <amerey@redhat.com>
libelf/gelf_update_move.c

index 4190ee30d0a580d94bedea116ead525256e99df4..2b12c7eb5efa4021697d771fd125055549fc2d0b 100644 (file)
 int
 gelf_update_move (Elf_Data *data, int ndx, GElf_Move *src)
 {
+  int result = 0;
   Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+  Elf *elf;
 
   if (data == NULL)
-    return 0;
+    return result;
 
-  /* 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));
-
-  /* Check whether we have to resize the data buffer.  */
-  if (INVALID_NDX (ndx, GElf_Move, &data_scn->d))
+  if (unlikely (data->d_type != ELF_T_MOVE))
     {
-      __libelf_seterrno (ELF_E_INVALID_INDEX);
-      return 0;
+      /* The type of the data better should match.  */
+      __libelf_seterrno (ELF_E_DATA_MISMATCH);
+      return result;
     }
 
-  if (unlikely (data_scn->d.d_type != ELF_T_MOVE))
+  elf = data_scn->s->elf;
+  rwlock_wrlock (elf->lock);
+
+  if (elf->class == ELFCLASS32)
     {
-      /* The type of the data better should match.  */
-      __libelf_seterrno (ELF_E_DATA_MISMATCH);
-      return 0;
+      Elf32_Move *move;
+
+      /* Check whether input values are too large for 32 bit conversion.  */
+      if (unlikely (src->m_poffset > 0xffffffffull)
+         || unlikely (GELF_M_SYM (src->m_info) > 0xffffff)
+         || unlikely (GELF_M_SIZE (src->m_info) > 0xff))
+       {
+         __libelf_seterrno (ELF_E_INVALID_DATA);
+         goto out;
+       }
+
+      /* Check whether we have to resize the data buffer.  */
+      if (INVALID_NDX (ndx, Elf32_Move, data))
+       {
+         __libelf_seterrno (ELF_E_INVALID_INDEX);
+         goto out;
+       }
+
+      move = &((Elf32_Move *) data->d_buf)[ndx];
+
+      move->m_value = src->m_value;
+      move->m_info = ELF32_M_INFO (GELF_M_SYM (src->m_info),
+                                  GELF_M_SIZE (src->m_info));
+      move->m_poffset = src->m_poffset;
+      move->m_repeat = src->m_repeat;
+      move->m_stride = src->m_stride;
     }
+  else
+    {
+      eu_static_assert (sizeof (GElf_Move) == sizeof (Elf64_Move));
 
-  rwlock_wrlock (data_scn->s->elf->lock);
+      /* Check whether we have to resize the data buffer.  */
+      if (INVALID_NDX (ndx, GElf_Move, data))
+       {
+         __libelf_seterrno (ELF_E_INVALID_INDEX);
+         goto out;
+       }
+
+      ((Elf64_Move *) data->d_buf)[ndx] = *src;
+    }
 
-  ((GElf_Move *) data_scn->d.d_buf)[ndx] = *src;
+  result = 1;
 
   /* Mark the section as modified.  */
   data_scn->s->flags |= ELF_F_DIRTY;
 
-  rwlock_unlock (data_scn->s->elf->lock);
+ out:
+  rwlock_unlock (elf->lock);
 
-  return 1;
+  return result;
 }