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;