fix for [#17783] problem when packing wav
authorCampbell Barton <ideasman42@gmail.com>
Sun, 12 Oct 2008 00:51:55 +0000 (00:51 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 12 Oct 2008 00:51:55 +0000 (00:51 +0000)
"data" is aligned differently in this wave file and the buffer was read past its allocated length.

Fix this by searching for the buffer in increments of 2 (this finds the "data" for the wav file)
added a check not to allow the search to go past the buffer length, so corrupt wave files should not crash.

intern/SoundSystem/SND_Utils.h
intern/SoundSystem/fmod/SND_FmodDevice.cpp
intern/SoundSystem/intern/SND_Utils.cpp

index c54aa434eec292381c02a8c8dcbd1d556aeeeb61..26cf1bda11cc19dab04986825563f95803393676 100644 (file)
@@ -97,8 +97,8 @@ extern unsigned int SND_GetSampleFormat(void* sample);
 extern unsigned int SND_GetNumberOfChannels(void* sample);
 extern unsigned int SND_GetSampleRate(void* sample);
 extern unsigned int SND_GetBitRate(void* sample);
-extern unsigned int SND_GetNumberOfSamples(void* sample);
-extern unsigned int SND_GetHeaderSize(void* sample);
+extern unsigned int SND_GetNumberOfSamples(void* sample, int sample_length);
+extern unsigned int SND_GetHeaderSize(void* sample, int sample_length);
 extern unsigned int SND_GetExtraChunk(void* sample);
 
 extern void SND_GetSampleInfo(signed char* sample, SND_WaveSlot* waveslot);
index cc252954fea70e47fd210cd46700fcb5def9eb00..3ba0802a5b046fd80d5fc2b9c16ae035d61083fa 100644 (file)
@@ -162,7 +162,7 @@ SND_WaveSlot* SND_FmodDevice::LoadSample(const STR_String& name,
                                                int numberofchannels = SND_GetNumberOfChannels(memlocation);
                                                int samplerate = SND_GetSampleRate(memlocation);
                                                int bitrate = SND_GetBitRate(memlocation);
-                                               int numberofsamples = SND_GetNumberOfSamples(memlocation);
+                                               int numberofsamples = SND_GetNumberOfSamples(memlocation, size);
                                                
                                                waveslot->SetFileSize(size);
                                                waveslot->SetData(memlocation);
index 754c8b029a1a6c182d2d34b15d58389a09979a5e..58023dd5c500ae51a0b593114ea5cd97030566a7 100644 (file)
@@ -285,10 +285,9 @@ unsigned int SND_GetBitRate(void* sample)
 
 
 /* gets the length of the actual sample data (without the header) */
-unsigned int SND_GetNumberOfSamples(void* sample)
+unsigned int SND_GetNumberOfSamples(void* sample, int sample_length)
 {
        unsigned int chunklength, length = 0, offset = 16;
-       char data[4];
        
        if (CheckSample(sample))
        {
@@ -297,14 +296,15 @@ unsigned int SND_GetNumberOfSamples(void* sample)
                if (SND_fEndian == SND_endianBig) SWITCH_INT(chunklength);
 
                offset = offset + chunklength + 4;
-               memcpy(data, ((char*)sample) + offset, 4);
 
                /* This seems very unsafe, what if data is never found (f.i. corrupt file)... */
                // lets find "data"
-               while (memcmp(data, "data", 4))
+               while (memcmp(((char*)sample) + offset, "data", 4))
                {
-                       offset += 4;
-                       memcpy(data, ((char*)sample) + offset, 4);
+                       offset += 2;
+                       
+                       if (offset+4 > sample_length) /* save us from crashing */
+                               return 0;
                }
                offset += 4;
                memcpy(&length, ((char*)sample) + offset, 4);
@@ -319,10 +319,9 @@ unsigned int SND_GetNumberOfSamples(void* sample)
 
 
 /* gets the size of the entire header (file - sampledata) */
-unsigned int SND_GetHeaderSize(void* sample)
+unsigned int SND_GetHeaderSize(void* sample, int sample_length)
 {
        unsigned int chunklength, headersize = 0, offset = 16;
-       char data[4];
        
        if (CheckSample(sample))
        {
@@ -330,13 +329,14 @@ unsigned int SND_GetHeaderSize(void* sample)
                /* This was endian unsafe. See top of the file for the define. */
                if (SND_fEndian == SND_endianBig) SWITCH_INT(chunklength);
                offset = offset + chunklength + 4;
-               memcpy(data, ((char*)sample) + offset, 4);
 
                // lets find "data"
-               while (memcmp(data, "data", 4))
+               while (memcmp(((char*)sample) + offset, "data", 4))
                {
-                       offset += 4;
-                       memcpy(data, ((char*)sample) + offset, 4);
+                       offset += 2;
+                       
+                       if (offset+4 > sample_length) /* save us from crashing */
+                               return 0;
                }
                headersize = offset + 8;
        }
@@ -382,58 +382,60 @@ void SND_GetSampleInfo(signed char* sample, SND_WaveSlot* waveslot)
        if (CheckSample(sample))
        {
                memcpy(&fileheader, sample, sizeof(WavFileHeader));
-               fileheader.size = SND_GetHeaderSize(sample);
-               sample += sizeof(WavFileHeader);
-               fileheader.size = ((fileheader.size+1) & ~1) - 4;
+               fileheader.size = SND_GetHeaderSize(sample, waveslot->GetFileSize());
+               if (fileheader.size) { /* this may fail for corrupt files */
+                       sample += sizeof(WavFileHeader);
+                       fileheader.size = ((fileheader.size+1) & ~1) - 4;
 
-               while ((fileheader.size > 0) && (memcpy(&chunkheader, sample, sizeof(WavChunkHeader))))
-               {
-                       sample += sizeof(WavChunkHeader);
-                       if (!memcmp(chunkheader.id, "fmt ", 4))
-                       {
-                               memcpy(&fmtheader, sample, sizeof(WavFmtHeader));
-                               waveslot->SetSampleFormat(fmtheader.format);
-
-                               if (fmtheader.format == 0x0001)
-                               {
-                                       waveslot->SetNumberOfChannels(fmtheader.numberofchannels);
-                                       waveslot->SetBitRate(fmtheader.bitrate);
-                                       waveslot->SetSampleRate(fmtheader.samplerate);
-                                       sample += chunkheader.size;
-                               } 
-                               else
-                               {
-                                       memcpy(&fmtexheader, sample, sizeof(WavFmtExHeader));
-                                       sample += chunkheader.size;
-                               }
-                       }
-                       else if (!memcmp(chunkheader.id, "data", 4))
+                       while ((fileheader.size > 0) && (memcpy(&chunkheader, sample, sizeof(WavChunkHeader))))
                        {
-                               if (fmtheader.format == 0x0001)
+                               sample += sizeof(WavChunkHeader);
+                               if (!memcmp(chunkheader.id, "fmt ", 4))
                                {
-                                       waveslot->SetNumberOfSamples(chunkheader.size);
-                                       sample += chunkheader.size;
+                                       memcpy(&fmtheader, sample, sizeof(WavFmtHeader));
+                                       waveslot->SetSampleFormat(fmtheader.format);
+
+                                       if (fmtheader.format == 0x0001)
+                                       {
+                                               waveslot->SetNumberOfChannels(fmtheader.numberofchannels);
+                                               waveslot->SetBitRate(fmtheader.bitrate);
+                                               waveslot->SetSampleRate(fmtheader.samplerate);
+                                               sample += chunkheader.size;
+                                       } 
+                                       else
+                                       {
+                                               memcpy(&fmtexheader, sample, sizeof(WavFmtExHeader));
+                                               sample += chunkheader.size;
+                                       }
                                }
-                               else if (fmtheader.format == 0x0011)
+                               else if (!memcmp(chunkheader.id, "data", 4))
                                {
-                                       //IMA ADPCM
+                                       if (fmtheader.format == 0x0001)
+                                       {
+                                               waveslot->SetNumberOfSamples(chunkheader.size);
+                                               sample += chunkheader.size;
+                                       }
+                                       else if (fmtheader.format == 0x0011)
+                                       {
+                                               //IMA ADPCM
+                                       }
+                                       else if (fmtheader.format == 0x0055)
+                                       {
+                                               //MP3 WAVE
+                                       }
                                }
-                               else if (fmtheader.format == 0x0055)
+                               else if (!memcmp(chunkheader.id, "smpl", 4))
                                {
-                                       //MP3 WAVE
+                                       memcpy(&sampleheader, sample, sizeof(WavSampleHeader));
+                                       //loop = sampleheader.loops;
+                                       sample += chunkheader.size;
                                }
-                       }
-                       else if (!memcmp(chunkheader.id, "smpl", 4))
-                       {
-                               memcpy(&sampleheader, sample, sizeof(WavSampleHeader));
-                               //loop = sampleheader.loops;
-                               sample += chunkheader.size;
-                       }
-                       else
-                               sample += chunkheader.size;
+                               else
+                                       sample += chunkheader.size;
 
-                       sample += chunkheader.size & 1;
-                       fileheader.size -= (((chunkheader.size + 1) & ~1) + 8);
+                               sample += chunkheader.size & 1;
+                               fileheader.size -= (((chunkheader.size + 1) & ~1) + 8);
+                       }
                }
        }
 }