commit 4c2b88c7c64600b1c17a31af7e0f60039c65496b
parent cfc77bb0a8bbecafc760096463680cc273a0c82a
Author: Christian Grothoff <christian@grothoff.org>
Date: Wed, 29 Jul 2026 11:09:25 +0200
ensure struct is packed correctly
Diffstat:
1 file changed, 68 insertions(+), 18 deletions(-)
diff --git a/src/plugins/real_extractor.c b/src/plugins/real_extractor.c
@@ -25,7 +25,16 @@
*/
#include "platform.h"
#include "extractor.h"
-
+#include "le_architecture.h"
+
+/* The structs below describe on-disk layout and are overlaid directly
+ on the (unaligned) read buffer, so they must be packed: without that
+ the compiler is entitled to assume natural alignment and emit loads
+ that are undefined for the addresses they are actually used at -- and
+ fatal on a strict-alignment target. The attribute goes on the struct
+ rather than on each member because gcc ignores it on aggregate and
+ array members. */
+LE_NETWORK_STRUCT_BEGIN
struct MediaProperties
{
uint32_t object_id;
@@ -48,8 +57,10 @@ struct MediaProperties
uint32_t type_specific_len;
uint8_t[type_specific_len] type_specific_data;
*/
-};
+} LE_PACKED;
+LE_NETWORK_STRUCT_END
+ LE_NETWORK_STRUCT_BEGIN
struct ContentDescription
{
uint32_t object_id;
@@ -66,10 +77,43 @@ struct ContentDescription
uint16_t comment_len;
uint8_t[comment_len] comment;
*/
-};
+} LE_PACKED;
+LE_NETWORK_STRUCT_END
/* author, copyright and comment are supposed to be ASCII */
+/**
+ * Read a big-endian 16 bit value from @a p, which need not be aligned.
+ *
+ * @param p (unaligned) source
+ * @return the value in host byte order
+ */
+static uint16_t
+read_be16 (const void *p)
+{
+ uint16_t v;
+
+ memcpy (&v, p, sizeof (v));
+ return ntohs (v);
+}
+
+
+/**
+ * Read a big-endian 32 bit value from @a p, which need not be aligned.
+ *
+ * @param p (unaligned) source
+ * @return the value in host byte order
+ */
+static uint32_t
+read_be32 (const void *p)
+{
+ uint32_t v;
+
+ memcpy (&v, p, sizeof (v));
+ return ntohl (v);
+}
+
+
#define REAL_HEADER 0x2E524d46
#define MDPR_HEADER 0x4D445052
#define CONT_HEADER 0x434F4e54
@@ -157,7 +201,7 @@ processContentDescription (const struct ContentDescription *prop,
+ sizeof (uint16_t)
+ sizeof (struct ContentDescription))
return;
- author_len = ntohs (*(uint16_t *) &prop->data[title_len]);
+ author_len = read_be16 (&prop->data[title_len]);
if (prop_size <=
title_len
+ sizeof (uint16_t)
@@ -183,9 +227,9 @@ processContentDescription (const struct ContentDescription *prop,
+ sizeof (uint16_t)
+ sizeof (struct ContentDescription))
return;
- copyright_len = ntohs (*(uint16_t *) &prop->data[title_len
- + author_len
- + sizeof (uint16_t)]);
+ copyright_len = read_be16 (&prop->data[title_len
+ + author_len
+ + sizeof (uint16_t)]);
if (prop_size <=
title_len
+ sizeof (uint16_t)
@@ -217,10 +261,10 @@ processContentDescription (const struct ContentDescription *prop,
+ sizeof (uint16_t)
+ sizeof (struct ContentDescription))
return;
- comment_len = ntohs (*(uint16_t *) &prop->data[title_len
- + author_len
- + copyright_len
- + 2 * sizeof (uint16_t)]);
+ comment_len = read_be16 (&prop->data[title_len
+ + author_len
+ + copyright_len
+ + 2 * sizeof (uint16_t)]);
if (prop_size <
title_len
+ sizeof (uint16_t)
@@ -249,11 +293,14 @@ processContentDescription (const struct ContentDescription *prop,
}
+LE_NETWORK_STRUCT_BEGIN
struct RAFF_Header
{
uint16_t version;
-};
+} LE_PACKED;
+LE_NETWORK_STRUCT_END
+ LE_NETWORK_STRUCT_BEGIN
struct RAFF3_Header
{
uint8_t unknown[10];
@@ -267,12 +314,14 @@ struct RAFF3_Header
uint8_t copyright[clen];
uint8_t aplen;
uint8_t app[aplen]; */
-};
+} LE_PACKED;
+LE_NETWORK_STRUCT_END
#define RAFF3_HDR_SIZE 14
+LE_NETWORK_STRUCT_BEGIN
struct RAFF4_Header
{
uint16_t version;
@@ -303,7 +352,8 @@ struct RAFF4_Header
uint8_t copyright[clen];
uint8_t aplen;
uint8_t app[aplen]; */
-};
+} LE_PACKED;
+LE_NETWORK_STRUCT_END
#define RAFF4_HDR_SIZE 53
@@ -497,7 +547,7 @@ extract_real (struct EXTRACTOR_ExtractContext *ec,
if ( (pos + 8 > size) ||
(pos + 8 < pos) ||
- (pos + (length = ntohl (((uint32_t *) (data + pos))[1])) > size) )
+ (pos + (length = read_be32 ((const char *) data + pos + 4)) > size) )
{
uint64_t noff;
void *in;
@@ -520,14 +570,14 @@ extract_real (struct EXTRACTOR_ExtractContext *ec,
/* re-read the atom header from the freshly filled buffer;
the previous value of 'length' refers to the old buffer
(or was never assigned due to short-circuit evaluation) */
- length = ntohl (((uint32_t *) (data + pos))[1]);
+ length = read_be32 ((const char *) data + pos + 4);
}
if (length <= 8)
return;
if ( (pos + length > size) ||
(pos + length < pos) )
return;
- switch (ntohl (((uint32_t *) (data + pos))[0]))
+ switch (read_be32 ((const char *) data + pos))
{
case MDPR_HEADER:
processMediaProperties (data + pos,
@@ -564,7 +614,7 @@ EXTRACTOR_real_extract_method (struct EXTRACTOR_ExtractContext *ec)
sizeof (struct RAFF4_Header) + 4 * 256);
if (n < (ssize_t) sizeof (uint32_t))
return;
- switch (ntohl (*(uint32_t *) data))
+ switch (read_be32 (data))
{
case RAFF4_HEADER:
extract_raff (ec,