]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
PR 33721 load/store of misaligned address
authorAlan Modra <amodra@gmail.com>
Tue, 16 Dec 2025 21:30:24 +0000 (08:00 +1030)
committerAlan Modra <amodra@gmail.com>
Tue, 16 Dec 2025 21:30:24 +0000 (08:00 +1030)
This fixes PR33721 by a common technique of declaring a packed struct
to access unaligned integer fields.  (See eg. linux kernel
include/vdso/unaligned.h)  I've tidied the PR29856 fix for a similar
bug too (not that there was anything wrong with that fix).

PR 33721
PR 29856
* sframe.c (flip_fre_start_address): Use a packed struct to
access 2-byte and 4-byte unaligned fields.  Make addr a void*.
(sframe_decode_fre_start_address): Similarly, and remove
unnecessary casts.  Always set *fre_start_addr.

libsframe/sframe.c

index 0dcc782b1f6c76a842208b8afc398f64aecb615f..3a02a76a2a969d8244db540c139714c3ab3d95f7 100644 (file)
@@ -311,17 +311,17 @@ sframe_header_sanity_check_p (const sframe_header *hp)
 /* Flip the start address pointed to by FP.  */
 
 static void
-flip_fre_start_address (char *addr, uint32_t fre_type)
+flip_fre_start_address (void *addr, uint32_t fre_type)
 {
   if (fre_type == SFRAME_FRE_TYPE_ADDR2)
     {
-      uint16_t *start_addr = (uint16_t *)addr;
-      swap_thing (*start_addr);
+      struct { uint16_t x; } ATTRIBUTE_PACKED *p = addr;
+      swap_thing (p->x);
     }
   else if (fre_type == SFRAME_FRE_TYPE_ADDR4)
     {
-      uint32_t *start_addr = (uint32_t *)addr;
-      swap_thing (*start_addr);
+      struct { uint32_t x; } ATTRIBUTE_PACKED *p = addr;
+      swap_thing (p->x);
     }
 }
 
@@ -938,42 +938,34 @@ sframe_frame_row_entry_copy (sframe_frame_row_entry *dst,
    Returns 0 on success, SFRAME_ERR otherwise.  */
 
 static int
-sframe_decode_fre_start_address (const char *fre_buf,
+sframe_decode_fre_start_address (const void *fre_buf,
                                 uint32_t *fre_start_addr,
                                 uint32_t fre_type)
 {
   uint32_t saddr = 0;
   int err = 0;
-  size_t addr_size = 0;
-
-  addr_size = sframe_fre_start_addr_size (fre_type);
 
   if (fre_type == SFRAME_FRE_TYPE_ADDR1)
     {
-      uint8_t *uc = (uint8_t *)fre_buf;
-      saddr = (uint32_t)*uc;
+      const uint8_t *uc = fre_buf;
+      saddr = *uc;
     }
   else if (fre_type == SFRAME_FRE_TYPE_ADDR2)
     {
-      uint16_t *ust = (uint16_t *)fre_buf;
-      /* SFrame is an unaligned on-disk format.  Using memcpy helps avoid the
-        use of undesirable unaligned loads.  See PR libsframe/29856.  */
-      uint16_t tmp = 0;
-      memcpy (&tmp, ust, addr_size);
-      saddr = (uint32_t)tmp;
+      /* SFrame is an unaligned on-disk format.  See PR libsframe/29856.  */
+      const struct { uint16_t x; } ATTRIBUTE_PACKED *p = fre_buf;
+      saddr = p->x;
     }
   else if (fre_type == SFRAME_FRE_TYPE_ADDR4)
     {
-      uint32_t *uit = (uint32_t *)fre_buf;
-      uint32_t tmp = 0;
-      memcpy (&tmp, uit, addr_size);
-      saddr = (uint32_t)tmp;
+      const struct { uint32_t x; } ATTRIBUTE_PACKED *p = fre_buf;
+      saddr = p->x;
     }
   else
-    return sframe_set_errno (&err, SFRAME_ERR_INVAL);
+    sframe_set_errno (&err, SFRAME_ERR_INVAL);
 
   *fre_start_addr = saddr;
-  return 0;
+  return err;
 }
 
 /* Decode a frame row entry FRE which starts at location FRE_BUF.  The function