From 57b98d5a8cebf8d5205a2654fd2d1a69d21c8955 Mon Sep 17 00:00:00 2001 From: dmitrykos Date: Sun, 21 Oct 2018 13:21:28 +0300 Subject: [PATCH] wasapi: fixed MonoToStereo converter could write beyond the allowed memory region if sample format is packed 24-bit integer, fixed DEF file by adding missing WASAPI API --- build/msvc/portaudio.def | 18 +++-- src/hostapi/wasapi/pa_win_wasapi.c | 114 ++++++++++++++++++++++------- 2 files changed, 99 insertions(+), 33 deletions(-) diff --git a/build/msvc/portaudio.def b/build/msvc/portaudio.def index bdaa8ee..87b2559 100644 --- a/build/msvc/portaudio.def +++ b/build/msvc/portaudio.def @@ -41,10 +41,14 @@ PaUtil_InitializeX86PlainConverters @52 PaAsio_GetInputChannelName @53 PaAsio_GetOutputChannelName @54 PaUtil_SetDebugPrintFunction @55 -PaWasapi_GetDeviceDefaultFormat @56 -PaWasapi_GetDeviceRole @57 -PaWasapi_ThreadPriorityBoost @58 -PaWasapi_ThreadPriorityRevert @59 -PaWasapi_GetFramesPerHostBuffer @60 -PaWasapi_GetJackDescription @61 -PaWasapi_GetJackCount @62 \ No newline at end of file +PaWasapi_GetAudioClient @56 +PaWasapi_UpdateDeviceList @57 +PaWasapi_GetDeviceCurrentFormat @58 +PaWasapi_GetDeviceDefaultFormat @59 +PaWasapi_GetDeviceRole @60 +PaWasapi_ThreadPriorityBoost @61 +PaWasapi_ThreadPriorityRevert @62 +PaWasapi_GetFramesPerHostBuffer @63 +PaWasapi_GetJackCount @64 +PaWasapi_GetJackDescription @65 +PaWasapi_SetDefaultInterfaceId @66 \ No newline at end of file diff --git a/src/hostapi/wasapi/pa_win_wasapi.c b/src/hostapi/wasapi/pa_win_wasapi.c index 8b4e2b2..32e6d2d 100644 --- a/src/hostapi/wasapi/pa_win_wasapi.c +++ b/src/hostapi/wasapi/pa_win_wasapi.c @@ -587,7 +587,7 @@ static HRESULT UnmarshalStreamComPointers(PaWasapiStream *stream); static void ReleaseUnmarshaledSubComPointers(PaWasapiSubStream *substream); static void ReleaseUnmarshaledComPointers(PaWasapiStream *stream); -// Local stream methods +// Local methods static void _StreamOnStop(PaWasapiStream *stream); static void _StreamFinish(PaWasapiStream *stream); static void _StreamCleanup(PaWasapiStream *stream); @@ -595,6 +595,7 @@ static HRESULT _PollGetOutputFramesAvailable(PaWasapiStream *stream, UINT32 *ava static HRESULT _PollGetInputFramesAvailable(PaWasapiStream *stream, UINT32 *available); static void *PaWasapi_ReallocateMemory(void *prev, size_t size); static void PaWasapi_FreeMemory(void *ptr); +static PaSampleFormat WaveToPaFormat(const WAVEFORMATEXTENSIBLE *fmtext); // Local statics @@ -1263,27 +1264,88 @@ EMixDirection; // ------------------------------------------------------------------------------------------ static void _MixMonoToStereo_1TO2_8(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_1_TO_2(BYTE); } static void _MixMonoToStereo_1TO2_16(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_1_TO_2(short); } -static void _MixMonoToStereo_1TO2_24(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_1_TO_2(int); /* !!! int24 data is contained in 32-bit containers*/ } +static void _MixMonoToStereo_1TO2_8_24(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_1_TO_2(int); /* !!! int24 data is contained in 32-bit containers*/ } static void _MixMonoToStereo_1TO2_32(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_1_TO_2(int); } static void _MixMonoToStereo_1TO2_32f(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_1_TO_2(float); } +static void _MixMonoToStereo_1TO2_24(void *__to, const void *__from, UINT32 count) +{ + const UCHAR * __restrict from = (const UCHAR *)__from; + UCHAR * __restrict to = (UCHAR *)__to; + const UCHAR * __restrict end = to + (count * (2 * 3)); + + while (to != end) + { + to[0] = to[3] = from[0]; + to[1] = to[4] = from[1]; + to[2] = to[5] = from[2]; + + from += 3; + to += (2 * 3); + } +} // ------------------------------------------------------------------------------------------ static void _MixMonoToStereo_2TO1_8(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_2_TO_1_INT32(BYTE); } static void _MixMonoToStereo_2TO1_16(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_2_TO_1_INT32(short); } -static void _MixMonoToStereo_2TO1_24(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_2_TO_1_INT32(int); /* !!! int24 data is contained in 32-bit containers*/ } +static void _MixMonoToStereo_2TO1_8_24(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_2_TO_1_INT32(int); /* !!! int24 data is contained in 32-bit containers*/ } static void _MixMonoToStereo_2TO1_32(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_2_TO_1_INT64(int); } static void _MixMonoToStereo_2TO1_32f(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_2_TO_1_FLT32(float); } +static void _MixMonoToStereo_2TO1_24(void *__to, const void *__from, UINT32 count) +{ + const UCHAR * __restrict from = (const UCHAR *)__from; + UCHAR * __restrict to = (UCHAR *)__to; + const UCHAR * __restrict end = to + (count * 3); + PaInt32 tempL, tempR, tempM; + + while (to != end) + { + tempL = (((PaInt32)from[0]) << 8); + tempL = tempL | (((PaInt32)from[1]) << 16); + tempL = tempL | (((PaInt32)from[2]) << 24); + + tempR = (((PaInt32)from[3]) << 8); + tempR = tempR | (((PaInt32)from[4]) << 16); + tempR = tempR | (((PaInt32)from[5]) << 24); + + tempM = (tempL + tempR) >> 1; + + to[0] = (UCHAR)(tempM >> 8); + to[1] = (UCHAR)(tempM >> 16); + to[2] = (UCHAR)(tempM >> 24); + + from += (2 * 3); + to += 3; + } +} // ------------------------------------------------------------------------------------------ static void _MixMonoToStereo_2TO1_8_L(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_2_TO_1_L(BYTE); } static void _MixMonoToStereo_2TO1_16_L(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_2_TO_1_L(short); } -static void _MixMonoToStereo_2TO1_24_L(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_2_TO_1_L(int); /* !!! int24 data is contained in 32-bit containers*/ } +static void _MixMonoToStereo_2TO1_8_24_L(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_2_TO_1_L(int); /* !!! int24 data is contained in 32-bit containers*/ } static void _MixMonoToStereo_2TO1_32_L(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_2_TO_1_L(int); } static void _MixMonoToStereo_2TO1_32f_L(void *__to, const void *__from, UINT32 count) { _WASAPI_MONO_TO_STEREO_MIXER_2_TO_1_L(float); } +static void _MixMonoToStereo_2TO1_24_L(void *__to, const void *__from, UINT32 count) +{ + const UCHAR * __restrict from = (const UCHAR *)__from; + UCHAR * __restrict to = (UCHAR *)__to; + const UCHAR * __restrict end = to + (count * 3); + + while (to != end) + { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + + from += (2 * 3); + to += 3; + } +} // ------------------------------------------------------------------------------------------ -static MixMonoToStereoF GetMonoToStereoMixer(PaSampleFormat format, EMixDirection dir) +static MixMonoToStereoF GetMonoToStereoMixer(const WAVEFORMATEXTENSIBLE *fmtext, EMixDirection dir) { + PaSampleFormat format = WaveToPaFormat(fmtext); + switch (dir) { case MIX_DIR__1TO2: @@ -1291,7 +1353,7 @@ static MixMonoToStereoF GetMonoToStereoMixer(PaSampleFormat format, EMixDirectio { case paUInt8: return _MixMonoToStereo_1TO2_8; case paInt16: return _MixMonoToStereo_1TO2_16; - case paInt24: return _MixMonoToStereo_1TO2_24; + case paInt24: return (fmtext->Format.wBitsPerSample == 32 ? _MixMonoToStereo_1TO2_8_24 : _MixMonoToStereo_1TO2_24); case paInt32: return _MixMonoToStereo_1TO2_32; case paFloat32: return _MixMonoToStereo_1TO2_32f; } @@ -1302,7 +1364,7 @@ static MixMonoToStereoF GetMonoToStereoMixer(PaSampleFormat format, EMixDirectio { case paUInt8: return _MixMonoToStereo_2TO1_8; case paInt16: return _MixMonoToStereo_2TO1_16; - case paInt24: return _MixMonoToStereo_2TO1_24; + case paInt24: return (fmtext->Format.wBitsPerSample == 32 ? _MixMonoToStereo_2TO1_8_24 : _MixMonoToStereo_2TO1_24); case paInt32: return _MixMonoToStereo_2TO1_32; case paFloat32: return _MixMonoToStereo_2TO1_32f; } @@ -1313,7 +1375,7 @@ static MixMonoToStereoF GetMonoToStereoMixer(PaSampleFormat format, EMixDirectio { case paUInt8: return _MixMonoToStereo_2TO1_8_L; case paInt16: return _MixMonoToStereo_2TO1_16_L; - case paInt24: return _MixMonoToStereo_2TO1_24_L; + case paInt24: return (fmtext->Format.wBitsPerSample == 32 ? _MixMonoToStereo_2TO1_8_24_L : _MixMonoToStereo_2TO1_24_L); case paInt32: return _MixMonoToStereo_2TO1_32_L; case paFloat32: return _MixMonoToStereo_2TO1_32f_L; } @@ -2254,27 +2316,27 @@ static void LogWAVEFORMATEXTENSIBLE(const WAVEFORMATEXTENSIBLE *in) } // ------------------------------------------------------------------------------------------ -static PaSampleFormat WaveToPaFormat(const WAVEFORMATEXTENSIBLE *in) +PaSampleFormat WaveToPaFormat(const WAVEFORMATEXTENSIBLE *fmtext) { - const WAVEFORMATEX *old = (WAVEFORMATEX *)in; + const WAVEFORMATEX *fmt = (WAVEFORMATEX *)fmtext; - switch (old->wFormatTag) + switch (fmt->wFormatTag) { case WAVE_FORMAT_EXTENSIBLE: { - if (IsEqualGUID(&in->SubFormat, &pa_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) + if (IsEqualGUID(&fmtext->SubFormat, &pa_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) { - if (in->Samples.wValidBitsPerSample == 32) + if (fmtext->Samples.wValidBitsPerSample == 32) return paFloat32; } else - if (IsEqualGUID(&in->SubFormat, &pa_KSDATAFORMAT_SUBTYPE_PCM)) + if (IsEqualGUID(&fmtext->SubFormat, &pa_KSDATAFORMAT_SUBTYPE_PCM)) { - switch (old->wBitsPerSample) + switch (fmt->wBitsPerSample) { - case 32: return paInt32; - case 24: return paInt24; - case 8: return paUInt8; - case 16: return paInt16; + case 32: return paInt32; + case 24: return paInt24; + case 16: return paInt16; + case 8: return paUInt8; } } break; } @@ -2283,12 +2345,12 @@ static PaSampleFormat WaveToPaFormat(const WAVEFORMATEXTENSIBLE *in) return paFloat32; case WAVE_FORMAT_PCM: { - switch (old->wBitsPerSample) + switch (fmt->wBitsPerSample) { - case 32: return paInt32; - case 24: return paInt24; - case 8: return paUInt8; - case 16: return paInt16; + case 32: return paInt32; + case 24: return paInt24; + case 16: return paInt16; + case 8: return paUInt8; } break; } } @@ -2803,7 +2865,7 @@ static HRESULT CreateAudioClient(PaWasapiStream *pStream, PaWasapiSubStream *pSu }*/ // select mixer - pSub->monoMixer = GetMonoToStereoMixer(WaveToPaFormat(&pSub->wavex), (pInfo->flow == eRender ? MIX_DIR__1TO2 : MIX_DIR__2TO1_L)); + pSub->monoMixer = GetMonoToStereoMixer(&pSub->wavex, (pInfo->flow == eRender ? MIX_DIR__1TO2 : MIX_DIR__2TO1_L)); if (pSub->monoMixer == NULL) { (*pa_error) = paInvalidChannelCount; @@ -3140,7 +3202,7 @@ static HRESULT CreateAudioClient(PaWasapiStream *pStream, PaWasapiSubStream *pSu }*/ // Select mixer - pSub->monoMixer = GetMonoToStereoMixer(WaveToPaFormat(&pSub->wavex), (pInfo->flow == eRender ? MIX_DIR__1TO2 : MIX_DIR__2TO1_L)); + pSub->monoMixer = GetMonoToStereoMixer(&pSub->wavex, (pInfo->flow == eRender ? MIX_DIR__1TO2 : MIX_DIR__2TO1_L)); if (pSub->monoMixer == NULL) { (*pa_error) = paInvalidChannelCount; -- 2.43.0