Merge branch 'parse-bad-wav'

Fix multiple problems with parsing untrusted input data in wxSound.

Closes #11855.
This commit is contained in:
Vadim Zeitlin 2017-12-30 22:52:14 +01:00
commit 0730236fa8

View File

@ -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)