From 06bcf8db9fd22ebfea5745238b034691e18e8a17 Mon Sep 17 00:00:00 2001 From: Tom M Date: Sat, 10 Nov 2018 08:07:30 +0100 Subject: [PATCH] Fix an incorrectly aligned result when converting between pointer types (#457) fix alignment issue of idlist --- src/sfloader/fluid_sffile.c | 53 ++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/src/sfloader/fluid_sffile.c b/src/sfloader/fluid_sffile.c index b3e64cc3..40055e81 100644 --- a/src/sfloader/fluid_sffile.c +++ b/src/sfloader/fluid_sffile.c @@ -77,9 +77,31 @@ enum SM24_ID }; -static const char idlist[] = {"RIFFLISTsfbkINFOsdtapdtaifilisngINAMiromiverICRDIENGIPRD" - "ICOPICMTISFTsnamsmplphdrpbagpmodpgeninstibagimodigenshdrsm24" - }; +/* + * This declares a char array containing the SF2 chunk identifiers. This + * array is being accessed like an uint32 below to simplify id comparison. + * To make sure it is suitably aligned for uint32 access, we must wrap it + * inside a union along with a uint32 telling the compiler to align it + * for integer access and avoiding undefined behaviour. + * This basically is the C89 equivalent to what is written in C11 as: + * alignas(uint32_t) static const char idlist[] = {}; + * + * See: EXP36-C. Do not cast pointers into more strictly aligned pointer + * types - SEI CERT C Coding Standard + */ +static const union fluid_idlist +{ + /* + * Cannot be char c[ ], because in C89, arrays wraped in unions + * must have a fixed size. Otherwise the size of the union would depend + * on the initialization of its first member, which results in + * different sizes for different instances of the same union type. + */ + char c[116]; + uint32_t i; +} idlist = {"RIFFLISTsfbkINFOsdtapdtaifilisngINAMiromiverICRDIENGIPRD" + "ICOPICMTISFTsnamsmplphdrpbagpmodpgeninstibagimodigenshdrsm24" + }; /* generator types */ @@ -183,7 +205,7 @@ static const unsigned short invalid_preset_gen[] = }; -#define CHNKIDSTR(id) &idlist[(id - 1) * 4] +#define CHNKIDSTR(id) &idlist.c[(id - 1) * 4] /* sfont file chunk sizes */ #define SF_PHDR_SIZE (38) @@ -284,7 +306,7 @@ static int load_shdr(SFData *sf, unsigned int size); static int fixup_pgen(SFData *sf); static int fixup_igen(SFData *sf); -static int chunkid(unsigned int id); +static int chunkid(uint32_t id); static int read_listchunk(SFData *sf, SFChunk *chunk); static int pdtahelper(SFData *sf, unsigned int expid, unsigned int reclen, SFChunk *chunk, int *size); static int preset_compare_func(void *a, void *b); @@ -486,14 +508,12 @@ void fluid_sffile_close(SFData *sf) */ /* sound font file load functions */ -static int chunkid(unsigned int id) +static int chunkid(uint32_t id) { unsigned int i; - const unsigned int *p; + const uint32_t *p = &idlist.i; - p = (const unsigned int *)&idlist; - - for(i = 0; i < sizeof(idlist) / sizeof(int); i++, p += 1) + for(i = 0; i < sizeof(idlist) / sizeof(idlist.i); i++, p += 1) { if(*p == id) { @@ -987,6 +1007,7 @@ static int load_phdr(SFData *sf, int size) FLUID_LOG(FLUID_ERR, "Out of memory"); return FALSE; } + sf->preset = fluid_list_append(sf->preset, preset); preset->zone = NULL; /* In case of failure, fluid_sffile_close can cleanup */ READSTR(sf, &preset->name); /* possible read failure ^ */ @@ -1078,6 +1099,7 @@ static int load_pbag(SFData *sf, int size) FLUID_LOG(FLUID_ERR, "Out of memory"); return FALSE; } + p2->data = z; z->gen = NULL; /* Init gen and mod before possible failure, */ z->mod = NULL; /* to ensure proper cleanup (fluid_sffile_close) */ @@ -1211,6 +1233,7 @@ static int load_pmod(SFData *sf, int size) FLUID_LOG(FLUID_ERR, "Out of memory"); return FALSE; } + p3->data = m; READW(sf, m->src); READW(sf, m->dest); @@ -1367,6 +1390,7 @@ static int load_pgen(SFData *sf, int size) FLUID_LOG(FLUID_ERR, "Out of memory"); return FALSE; } + p3->data = g; g->id = genid; } @@ -1508,6 +1532,7 @@ static int load_ihdr(SFData *sf, int size) FLUID_LOG(FLUID_ERR, "Out of memory"); return FALSE; } + sf->inst = fluid_list_append(sf->inst, p); p->zone = NULL; /* For proper cleanup if fail (fluid_sffile_close) */ p->idx = i; @@ -1593,6 +1618,7 @@ static int load_ibag(SFData *sf, int size) FLUID_LOG(FLUID_ERR, "Out of memory"); return FALSE; } + p2->data = z; z->gen = NULL; /* In case of failure, */ z->mod = NULL; /* fluid_sffile_close can clean up */ @@ -1727,6 +1753,7 @@ static int load_imod(SFData *sf, int size) FLUID_LOG(FLUID_ERR, "Out of memory"); return FALSE; } + p3->data = m; READW(sf, m->src); READW(sf, m->dest); @@ -1872,6 +1899,7 @@ static int load_igen(SFData *sf, int size) FLUID_LOG(FLUID_ERR, "Out of memory"); return FALSE; } + p3->data = g; g->id = genid; } @@ -2011,6 +2039,7 @@ static int load_shdr(SFData *sf, unsigned int size) FLUID_LOG(FLUID_ERR, "Out of memory"); return FALSE; } + sf->sample = fluid_list_append(sf->sample, p); READSTR(sf, &p->name); READD(sf, p->start); @@ -2138,7 +2167,7 @@ static void delete_preset(SFPreset *preset) } delete_fluid_list(preset->zone); - + FLUID_FREE(preset); } @@ -2162,7 +2191,7 @@ static void delete_inst(SFInst *inst) } delete_fluid_list(inst->zone); - + FLUID_FREE(inst); }