commit cfc77bb0a8bbecafc760096463680cc273a0c82a
parent 7587479919bef5cfaddebc4f2ce5bbecfe0c76c2
Author: Christian Grothoff <christian@grothoff.org>
Date: Wed, 29 Jul 2026 11:09:05 +0200
ensure struct is packed correctly
Diffstat:
1 file changed, 59 insertions(+), 9 deletions(-)
diff --git a/src/plugins/qt_extractor.c b/src/plugins/qt_extractor.c
@@ -35,6 +35,7 @@
#include <zlib.h>
#include <stdint.h>
#include <stdbool.h>
+#include "le_architecture.h"
/**
* Maximum size (in bytes) of a single top-level atom that we are willing
@@ -480,11 +481,19 @@ static ITTagConversionEntry it_to_extr_table[] = {
};
+/* 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 Atom
{
uint32_t size;
uint32_t type;
-};
+} LE_PACKED;
struct LongAtom
@@ -492,7 +501,8 @@ struct LongAtom
uint32_t one;
uint32_t type;
uint64_t size;
-};
+} LE_PACKED;
+LE_NETWORK_STRUCT_END
static uint64_t
@@ -507,6 +517,40 @@ ntohll (uint64_t n)
/**
+ * Read a big-endian 32 bit value from @a p, which need not be aligned.
+ * Casting the read buffer to `uint32_t *' has the same alignment problem
+ * as an unpacked struct does and is not fixed by packing.
+ *
+ * @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);
+}
+
+
+/**
+ * Read a big-endian 64 bit value from @a p, which need not be aligned.
+ *
+ * @param p (unaligned) source
+ * @return the value in host byte order
+ */
+static uint64_t
+read_be64 (const void *p)
+{
+ uint64_t v;
+
+ memcpy (&v, p, sizeof (v));
+ return ntohll (v);
+}
+
+
+/**
* Check if at position pos there is a valid atom.
* @return false if the atom is invalid, true if it is valid
*/
@@ -750,6 +794,7 @@ moovHandler (const char *input,
/* see http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap1/chapter_2_section_5.html */
+LE_NETWORK_STRUCT_BEGIN
struct FileType
{
struct Atom header;
@@ -759,7 +804,8 @@ struct FileType
unsigned int version;
/* compatible brands */
char compatibility[4];
-};
+} LE_PACKED;
+LE_NETWORK_STRUCT_END
static int
@@ -823,8 +869,8 @@ mvhdHandler (const char *input,
timeScale(4) duration(4) ... */
if (asize < hdr + 20)
return -1;
- timeScale = ntohl (*(const uint32_t *) &body[12]);
- duration = ntohl (*(const uint32_t *) &body[16]);
+ timeScale = read_be32 (&body[12]);
+ duration = read_be32 (&body[16]);
}
else if (1 == version)
{
@@ -832,8 +878,8 @@ mvhdHandler (const char *input,
timeScale(4) duration(8) ... */
if (asize < hdr + 32)
return -1;
- timeScale = ntohl (*(const uint32_t *) &body[20]);
- duration = ntohll (*(const uint64_t *) &body[24]);
+ timeScale = read_be32 (&body[20]);
+ duration = read_be64 (&body[24]);
}
else
{
@@ -852,6 +898,7 @@ mvhdHandler (const char *input,
}
+LE_NETWORK_STRUCT_BEGIN
struct CompressedMovieHeaderAtom
{
struct Atom cmovAtom;
@@ -859,7 +906,8 @@ struct CompressedMovieHeaderAtom
char compressor[4];
struct Atom cmvdAtom;
uint32_t decompressedSize;
-};
+} LE_PACKED;
+LE_NETWORK_STRUCT_END
static int
@@ -1014,12 +1062,14 @@ metaHandler (const char *input,
}
+LE_NETWORK_STRUCT_BEGIN
struct InternationalText
{
struct Atom header;
uint16_t length;
uint16_t language;
-};
+} LE_PACKED;
+LE_NETWORK_STRUCT_END
/*