libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

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:
Msrc/plugins/real_extractor.c | 86++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
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,