RIFF: added MTDF meta type, relaxed some conditions and moved an array to the stack

This commit is contained in:
Mathias Panzenböck 2018-01-13 06:09:54 +01:00
parent 9e7244c6f1
commit 3584d2093a

View File

@ -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;