diff --git a/src/unix/sound.cpp b/src/unix/sound.cpp index ae38289009..355fc8673d 100644 --- a/src/unix/sound.cpp +++ b/src/unix/sound.cpp @@ -651,35 +651,64 @@ bool wxSound::LoadWAV(const void* data_, size_t length, bool copyData) waveformat.uiBlockAlign = wxUINT16_SWAP_ON_BE(waveformat.uiBlockAlign); waveformat.uiBitsPerSample = wxUINT16_SWAP_ON_BE(waveformat.uiBitsPerSample); - // get the sound data size - wxUint32 ul; - memcpy(&ul, &data[FMT_INDEX + waveformat.uiSize + 12], 4); - ul = wxUINT32_SWAP_ON_BE(ul); - - if ( length < ul + FMT_INDEX + waveformat.uiSize + 16 ) - return false; - if (memcmp(data, "RIFF", 4) != 0) return false; if (memcmp(&data[WAVE_INDEX], "WAVE", 4) != 0) return false; if (memcmp(&data[FMT_INDEX], "fmt ", 4) != 0) return false; + + // Check that the format chunk size is correct: it must be 16 for PCM, + // which is the only format we handle. + if (waveformat.uiSize != 16) + return false; + if (memcmp(&data[FMT_INDEX + waveformat.uiSize + 8], "data", 4) != 0) return false; if (waveformat.uiFormatTag != WAVE_FORMAT_PCM) return false; - if (waveformat.ulSamplesPerSec != - waveformat.ulAvgBytesPerSec / waveformat.uiBlockAlign) + if (waveformat.ulAvgBytesPerSec != + waveformat.ulSamplesPerSec * waveformat.uiBlockAlign) + return false; + + // We divide by the sample size below to obtain the number of samples, so + // it definitely can't be 0. Also take care to avoid integer overflow when + // computing it. + unsigned tmp = waveformat.uiChannels; + if (tmp >= 0x10000) + return false; + + tmp *= waveformat.uiBitsPerSample; + + wxUint32 const sampleSize = tmp / 8; + if (!sampleSize) + return false; + + // get file size from header + wxUint32 chunkSize; + memcpy(&chunkSize, &data[4], 4); + chunkSize = wxUINT32_SWAP_ON_BE(chunkSize); + + // ensure file length is at least length in header + if (chunkSize > length - 8) + return false; + + // get the sound data size + wxUint32 ul; + memcpy(&ul, &data[FMT_INDEX + waveformat.uiSize + 12], 4); + ul = wxUINT32_SWAP_ON_BE(ul); + + // ensure we actually have at least that much data in the input + if (ul > length - FMT_INDEX - waveformat.uiSize - 16) return false; m_data = new wxSoundData; m_data->m_channels = waveformat.uiChannels; m_data->m_samplingRate = waveformat.ulSamplesPerSec; m_data->m_bitsPerSample = waveformat.uiBitsPerSample; - m_data->m_samples = ul / (m_data->m_channels * m_data->m_bitsPerSample / 8); + m_data->m_samples = ul / sampleSize; m_data->m_dataBytes = ul; if (copyData)