ref: c03ebff7de31f1208b35130e36be60f7c774ba2d
parent: 6edeaf06f5e6abd2c1e8f41f0ec0517abb43f613
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue Dec 26 21:48:45 EST 2023
wav: apparently fmt doesn't _always_ come after WAVE
--- a/wav.c
+++ b/wav.c
@@ -24,30 +24,8 @@
return -1;
}
p += 4; sz -= 4;
- if(memcmp(p, "fmt ", 4) != 0){- werrstr("no \"fmt \" subchunk");- return -1;
- }
- p += 4; sz -= 4;
- n = le32(p); sz -= 4;
-
- fmt = le16(p); sz -= 2; n -= 2;
- if(fmt != 1){- werrstr("not Microsoft PCM format: %d", fmt);- return -1;
- }
- info->channels = le16(p); sz -= 2; n -= 2;
- info->rate = le32(p); sz -= 4; n -= 4;
- p += 4+2; sz -= 4+2; n -= 4+2; /* skip ByteRate + BlockAlign */
- info->width = le16(p); sz -= 2; n -= 2;
- if((info->width % 8) != 0){- werrstr("invalid width: %d", info->width);- return -1;
- }
- info->width /= 8;
- info->loopofs = -1;
loopsamples = 0;
- p += n; sz -= n;
+ info->loopofs = -1;
for(; sz >= 8;){p += 4; sz -= 4;
@@ -54,33 +32,53 @@
n = le32(p); sz -= 4;
if(n > sz || n <= 0)
break;
- if(n >= 4){- if(memcmp(p-8, "cue ", 4) == 0){- i = le32(p); sz -= 4; n -= 4; /* CuePoints - usually two of those */
- if(i >= 1 && n >= i*6*4){+ if(n < 4)
+ goto skip;
+ if(memcmp(p-8, "fmt ", 4) == 0){+ fmt = le16(p); sz -= 2; n -= 2;
+ if(fmt != 1){+ werrstr("not Microsoft PCM format: %d", fmt);+ return -1;
+ }
+ info->channels = le16(p); sz -= 2; n -= 2;
+ info->rate = le32(p); sz -= 4; n -= 4;
+ p += 4+2; sz -= 4+2; n -= 4+2; /* skip ByteRate + BlockAlign */
+ info->width = le16(p); sz -= 2; n -= 2;
+ if((info->width % 8) != 0){+ werrstr("invalid width: %d", info->width);+ return -1;
+ }
+ info->width /= 8;
+ }else if(memcmp(p-8, "cue ", 4) == 0){+ i = le32(p); sz -= 4; n -= 4; /* CuePoints - usually two of those */
+ if(i >= 1 && n >= i*6*4){+ p += 5*4; sz -= 5*4; n -= 5*4; /* Name+Position+Chunk+ChunkStart+BlockStart */
+ info->loopofs = le32(p); sz -= 4; n -= 4;
+ /* FIXME(sigrid): check if this is needed and whether it works at all */
+ if(i > 1){p += 5*4; sz -= 5*4; n -= 5*4; /* Name+Position+Chunk+ChunkStart+BlockStart */
- info->loopofs = le32(p); sz -= 4; n -= 4;
- /* FIXME(sigrid): check if this is needed and whether it works at all */
- if(i > 1){- p += 5*4; sz -= 5*4; n -= 5*4; /* Name+Position+Chunk+ChunkStart+BlockStart */
- loopsamples = info->loopofs + le32(p); sz -= 4; n -= 4;
- }
- }
- }else if(memcmp(p-8, "data", 4) == 0 && info->dataofs == 0){- info->samples = n / info->width;
- info->dataofs = p - in;
- }else if(memcmp(p-8, "LIST", 4) == 0 && info->loopofs >= 0 && loopsamples == 0){- p += 4; sz -= 4; n -= 4; /* skip "adtl" */
- if(n >= 20 && memcmp(p, "ltxt", 4) == 0 && memcmp(p+16, "mark", 4) == 0){- p += 12; sz -= 12; n -= 12;
loopsamples = info->loopofs + le32(p); sz -= 4; n -= 4;
}
}
+ }else if(memcmp(p-8, "data", 4) == 0 && info->dataofs == 0){+ info->samples = n / info->width;
+ info->dataofs = p - in;
+ }else if(memcmp(p-8, "LIST", 4) == 0 && info->loopofs >= 0 && loopsamples == 0){+ p += 4; sz -= 4; n -= 4; /* skip "adtl" */
+ if(n >= 20 && memcmp(p, "ltxt", 4) == 0 && memcmp(p+16, "mark", 4) == 0){+ p += 12; sz -= 12; n -= 12;
+ loopsamples = info->loopofs + le32(p); sz -= 4; n -= 4;
+ }
}
+skip:
n = (n + 1) & ~1;
p += n; sz -= n;
}
+ if(info->width < 1 || info->channels < 1 || info->rate < 1){+ werrstr("invalid/missing fmt chunk?");+ return -1;
+ }
if(loopsamples > info->samples || info->loopofs > info->samples){ werrstr("invalid loop: (%d,%d) > %d", info->loopofs, loopsamples, info->samples);return -1;
--
⑨