libelf: Use offsetof to get field of unaligned
authorMark Wielaard <mark@klomp.org>
Tue, 14 Dec 2021 15:12:31 +0000 (16:12 +0100)
committerMark Wielaard <mark@klomp.org>
Thu, 16 Dec 2021 17:10:24 +0000 (18:10 +0100)
gcc undefined sanitizer flags:

elf_begin.c:230:18: runtime error: member access within misaligned
address 0xf796400a for type 'struct Elf64_Shdr', which requires 4 byte
alignment struct.

We aren't actually accessing the field member of the struct, but are
taking the address of it. Which the compiler can take as a hint that
the address is correctly aligned. But we can do the same by adding
the field offsetof to the base address. Which doesn't trigger a
runtime error.

Signed-off-by: Mark Wielaard <mark@klomp.org>
libelf/ChangeLog
libelf/elf_begin.c

index 041da9b..96059ef 100644 (file)
@@ -1,3 +1,8 @@
+2021-12-15  Mark Wielaard  <mark@klomp.org>
+
+       * elf_begin.c (get_shnum): Use offsetof to get field of unaligned
+       struct.
+
 2021-09-06  Dmitry V. Levin  <ldv@altlinux.org>
 
        * common.h (allocate_elf): Remove cast of calloc return value.
index 93d1e12..bd3399d 100644 (file)
@@ -1,5 +1,6 @@
 /* Create descriptor for processing file.
    Copyright (C) 1998-2010, 2012, 2014, 2015, 2016 Red Hat, Inc.
+   Copyright (C) 2021 Mark J. Wielaard <mark@klomp.org>
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 1998.
 
@@ -170,9 +171,10 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes,
              if (likely (map_address != NULL))
                /* gcc will optimize the memcpy to a simple memory
                   access while taking care of alignment issues.  */
-               memcpy (&size, &((Elf32_Shdr *) ((char *) map_address
-                                                + ehdr.e32->e_shoff
-                                                + offset))->sh_size,
+               memcpy (&size, ((char *) map_address
+                                        + ehdr.e32->e_shoff
+                                        + offset
+                                        + offsetof (Elf32_Shdr, sh_size)),
                        sizeof (Elf32_Word));
              else
                if (unlikely ((r = pread_retry (fildes, &size,
@@ -227,9 +229,10 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes,
              if (likely (map_address != NULL))
                /* gcc will optimize the memcpy to a simple memory
                   access while taking care of alignment issues.  */
-               memcpy (&size, &((Elf64_Shdr *) ((char *) map_address
-                                                + ehdr.e64->e_shoff
-                                                + offset))->sh_size,
+               memcpy (&size, ((char *) map_address
+                                        + ehdr.e64->e_shoff
+                                        + offset
+                                        + offsetof (Elf64_Shdr, sh_size)),
                        sizeof (Elf64_Xword));
              else
                if (unlikely ((r = pread_retry (fildes, &size,