From 3584d2093a4f668b94a7b1ccb1bcc350ed537bab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20Panzenb=C3=B6ck?= Date: Sat, 13 Jan 2018 06:09:54 +0100 Subject: [PATCH] RIFF: added MTDF meta type, relaxed some conditions and moved an array to the stack --- src/riff.c | 70 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/src/riff.c b/src/riff.c index 64c4ca0..ea0ea62 100644 --- a/src/riff.c +++ b/src/riff.c @@ -31,6 +31,8 @@ #define CHUNK(c1,c2,c3,c4,required) CHUNK_SPEC(0,c1,c2,c3,c4,0,required) #define END { 0, 0, 0, 0 } #define BODY(...) { __VA_ARGS__, END } +#define CHUNK_SPEC_COUNT(SPECS) ((sizeof(SPECS) / sizeof(struct riff_chunk_spec)) - 1) +#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) struct riff_chunk_spec { uint32_t metatype; @@ -215,6 +217,29 @@ static const struct riff_chunk_spec riff_webp_body[] = BODY( CHUNK('V','P','8','X', 0) ); +#define MAX_CHUNK_SPEC_COUNT \ + MAX(CHUNK_SPEC_COUNT(riff_empty_body), \ + MAX(CHUNK_SPEC_COUNT(riff_wav_body), \ + MAX(CHUNK_SPEC_COUNT(riff_avi_body), \ + MAX(CHUNK_SPEC_COUNT(riff_ani_fram_body), \ + MAX(CHUNK_SPEC_COUNT(riff_ani_body), \ + MAX(CHUNK_SPEC_COUNT(riff_pal_body), \ + MAX(CHUNK_SPEC_COUNT(riff_aud_body), \ + MAX(CHUNK_SPEC_COUNT(riff_dmbd_body), \ + MAX(CHUNK_SPEC_COUNT(riff_dmpr_body), \ + MAX(CHUNK_SPEC_COUNT(riff_dmcn_body), \ + MAX(CHUNK_SPEC_COUNT(riff_dsbc_body), \ + MAX(CHUNK_SPEC_COUNT(riff_dsfx_body), \ + MAX(CHUNK_SPEC_COUNT(riff_dmsc_body), \ + MAX(CHUNK_SPEC_COUNT(riff_sgt_body), \ + MAX(CHUNK_SPEC_COUNT(riff_sty_body), \ + MAX(CHUNK_SPEC_COUNT(riff_dmtl_body), \ + MAX(CHUNK_SPEC_COUNT(riff_dmtg_body), \ + MAX(CHUNK_SPEC_COUNT(riff_dmtk_body), \ + MAX(CHUNK_SPEC_COUNT(riff_dmbt_body), \ + MAX(CHUNK_SPEC_COUNT(riff_dmpt_body), \ + CHUNK_SPEC_COUNT(riff_webp_body))))))))))))))))))))) + static const struct riff_file_spec riff_file_specs[] = { { RIFF('W','A','V','E', riff_wav_body ), "wav" }, { RIFF('A','V','I',' ', riff_avi_body ), "avi" }, @@ -238,6 +263,7 @@ static const struct riff_file_spec riff_file_specs[] = { { RIFF('D','M','B','T', riff_dmbt_body), "riff" }, { RIFF('D','M','P','T', riff_dmpt_body), "riff" }, { RIFF('W','E','B','P', riff_webp_body), "webp" }, + { RIFF('M','T','D','F', 0 ), "mtd" }, { END, 0 } }; @@ -247,38 +273,26 @@ const uint8_t *riff_match(const uint8_t *data, size_t size, { if (spec->metatype) { - if (size < 12 || MAGIC(data) != spec->metatype) + if (size < 12 || MAGIC(data) != spec->metatype) { return NULL; + } - size_t chunk_size = le32toh(*(const uint32_t *)(data + 4)); - uint32_t type = MAGIC(data + 8); + const size_t chunk_size = le32toh(*(const uint32_t *)(data + 4)); + const uint32_t type = MAGIC(data + 8); - if (type != spec->type) + if (type != spec->type) { return NULL; + } - if (chunk_size > size - 8) + if (chunk_size > size - 8) { return NULL; + } // match sub chunks const struct riff_chunk_spec *body = spec->body; - uint32_t *counts = NULL; - if (body) - { - size_t count = 0; - for (const struct riff_chunk_spec *subspec = body; subspec->type; ++ subspec) - ++ count; + uint32_t counts[MAX_CHUNK_SPEC_COUNT] = { 0 }; - if (count > 0) - { - counts = (uint32_t *)calloc(count, sizeof(uint32_t)); - - if (!counts) { - perror("parsing RIFF structure"); - return NULL; - } - } - } - else + if (!body) { body = riff_empty_body; } @@ -294,10 +308,7 @@ const uint8_t *riff_match(const uint8_t *data, size_t size, size_t subchunk_size = le32toh(*(const uint32_t *)(subdata + 4)); if (subchunk_size > subsize - 8) - { - free(counts); - return NULL; - } + break; for (size_t i = 0;; ++ i) { @@ -315,7 +326,7 @@ const uint8_t *riff_match(const uint8_t *data, size_t size, subdata += subchunk_size + 8; } - + for (size_t i = 0;; ++ i) { const struct riff_chunk_spec *subspec = body + i; @@ -325,13 +336,10 @@ const uint8_t *riff_match(const uint8_t *data, size_t size, if (subspec->required && counts[i] == 0) { - free(counts); return NULL; } } - free(counts); - #if 0 // If the sub chunk matching code above delivers to many false positives this code could be used // instead. This code is not really correct, because sub chunks could theoretically occure in any @@ -354,7 +362,7 @@ const uint8_t *riff_match(const uint8_t *data, size_t size, if (size < 8 || MAGIC(data) != spec->type) return NULL; - size_t chunk_size = le32toh(*(const uint32_t *)(data + 4)); + const size_t chunk_size = le32toh(*(const uint32_t *)(data + 4)); if (chunk_size > size - 8) return NULL;