freerdp/channels-audin-tighten-parameter-checks.patch
2026-08-13 17:37:08 -04:00

229 lines
8.0 KiB
Diff

From 3b25c78c98d25b23246a5267d45f3654c2a8735d Mon Sep 17 00:00:00 2001
From: Armin Novak <armin.novak@thincast.com>
Date: Wed, 15 Jul 2026 17:52:28 +0200
Subject: [PATCH] [channels,audin] tighten parameter checks
---
channels/audin/client/alsa/audin_alsa.c | 4 +-
channels/audin/client/opensles/opensl_io.c | 43 +++++++++++++++-------
channels/audin/client/opensles/opensl_io.h | 5 +--
channels/audin/client/oss/audin_oss.c | 3 ++
channels/audin/client/sndio/audin_sndio.c | 9 +++--
channels/audin/client/winmm/audin_winmm.c | 17 +++++----
6 files changed, 51 insertions(+), 30 deletions(-)
diff --git a/channels/audin/client/alsa/audin_alsa.c b/channels/audin/client/alsa/audin_alsa.c
index e74097129..5b9f4ea5b 100644
--- a/channels/audin/client/alsa/audin_alsa.c
+++ b/channels/audin/client/alsa/audin_alsa.c
@@ -138,8 +138,8 @@ static DWORD WINAPI audin_alsa_thread_func(LPVOID arg)
goto out;
}
- buffer =
- (BYTE*)calloc(alsa->frames_per_packet + alsa->aformat.nBlockAlign, alsa->bytes_per_frame);
+ buffer = (BYTE*)calloc(1ull * alsa->frames_per_packet + alsa->aformat.nBlockAlign,
+ alsa->bytes_per_frame);
if (!buffer)
{
diff --git a/channels/audin/client/opensles/opensl_io.c b/channels/audin/client/opensles/opensl_io.c
index 39b3dc848..2f27bd60f 100644
--- a/channels/audin/client/opensles/opensl_io.c
+++ b/channels/audin/client/opensles/opensl_io.c
@@ -54,10 +54,10 @@ struct opensl_stream
SLRecordItf recorderRecord;
SLAndroidSimpleBufferQueueItf recorderBufferQueue;
- unsigned int inchannels;
- unsigned int sr;
- unsigned int buffersize;
- unsigned int bits_per_sample;
+ size_t inchannels;
+ size_t sr;
+ size_t buffersize;
+ size_t bits_per_sample;
queue_element* prep;
queue_element* next;
@@ -109,8 +109,8 @@ engine_end:
static SLresult openSLRecOpen(OPENSL_STREAM* p)
{
SLresult result;
- SLuint32 sr = p->sr;
- SLuint32 channels = p->inchannels;
+ SLuint32 sr = WINPR_ASSERTING_INT_CAST(SLuint32, p->sr);
+ SLuint32 channels = WINPR_ASSERTING_INT_CAST(SLuint32, p->inchannels);
WINPR_ASSERT(!p->recorderObject);
if (channels)
@@ -201,7 +201,10 @@ static SLresult openSLRecOpen(OPENSL_STREAM* p)
format_pcm.containerSize = 8;
}
else
- WINPR_ASSERT(0);
+ {
+ WLog_ERR(TAG, "bits_per_sample=%" PRIuz, p->bits_per_sample);
+ return -1;
+ }
SLDataSink audioSnk = { &loc_bq, &format_pcm };
// create audio recorder
@@ -306,24 +309,31 @@ static void opensles_queue_element_free(void* obj)
}
// open the android audio device for input
-OPENSL_STREAM* android_OpenRecDevice(void* context, opensl_receive_t receive, int sr,
- int inchannels, int bufferframes, int bits_per_sample)
+OPENSL_STREAM* android_OpenRecDevice(void* context, opensl_receive_t receive, size_t sr,
+ size_t inchannels, size_t bufferframes, size_t bits_per_sample)
{
- OPENSL_STREAM* p;
-
if (!context || !receive)
return NULL;
- p = (OPENSL_STREAM*)calloc(1, sizeof(OPENSL_STREAM));
+ OPENSL_STREAM* p = (OPENSL_STREAM*)calloc(1, sizeof(OPENSL_STREAM));
if (!p)
return NULL;
p->context = context;
p->receive = receive;
+ if (inchannels > INT32_MAX)
+ goto fail;
p->inchannels = inchannels;
+
+ if (sr > INT32_MAX)
+ goto fail;
p->sr = sr;
+
+ if (bufferframes > SIZE_MAX / 2)
+ goto fail;
p->buffersize = bufferframes;
+
p->bits_per_sample = bits_per_sample;
if ((p->bits_per_sample != 8) && (p->bits_per_sample != 16))
@@ -335,9 +345,14 @@ OPENSL_STREAM* android_OpenRecDevice(void* context, opensl_receive_t receive, in
if (openSLRecOpen(p) != SL_RESULT_SUCCESS)
goto fail;
+ const size_t bytesPerSample = p->bits_per_sample / 8ull;
+ if (p->buffersize >= SIZE_MAX / bytesPerSample)
+ goto fail;
+
+ const size_t queuesize = p->buffersize * bytesPerSample;
/* Create receive buffers, prepare them and start recording */
- p->prep = opensles_queue_element_new(p->buffersize * p->bits_per_sample / 8);
- p->next = opensles_queue_element_new(p->buffersize * p->bits_per_sample / 8);
+ p->prep = opensles_queue_element_new(queuesize);
+ p->next = opensles_queue_element_new(queuesize);
if (!p->prep || !p->next)
goto fail;
diff --git a/channels/audin/client/opensles/opensl_io.h b/channels/audin/client/opensles/opensl_io.h
index e99522cfe..07255de5c 100644
--- a/channels/audin/client/opensles/opensl_io.h
+++ b/channels/audin/client/opensles/opensl_io.h
@@ -51,13 +51,12 @@ extern "C"
size in frames. Returns a handle to the OpenSL stream
*/
FREERDP_LOCAL OPENSL_STREAM* android_OpenRecDevice(void* context, opensl_receive_t receive,
- int sr, int inchannels, int bufferframes,
- int bits_per_sample);
+ size_t sr, size_t inchannels,
+ size_t bufferframes, size_t bits_per_sample);
/*
Close the audio device
*/
FREERDP_LOCAL void android_CloseRecDevice(OPENSL_STREAM* p);
-
#ifdef __cplusplus
};
#endif
diff --git a/channels/audin/client/oss/audin_oss.c b/channels/audin/client/oss/audin_oss.c
index 8b6ad6cc5..c76326d9c 100644
--- a/channels/audin/client/oss/audin_oss.c
+++ b/channels/audin/client/oss/audin_oss.c
@@ -229,6 +229,9 @@ static DWORD WINAPI audin_oss_thread_func(LPVOID arg)
buffer_size =
(1ull * oss->FramesPerPacket * oss->format.nChannels * (oss->format.wBitsPerSample / 8ull));
+ if (buffer_size > INT32_MAX)
+ goto err_out;
+
buffer = (BYTE*)calloc((buffer_size + sizeof(void*)), sizeof(BYTE));
if (NULL == buffer)
diff --git a/channels/audin/client/sndio/audin_sndio.c b/channels/audin/client/sndio/audin_sndio.c
index af5426e72..655145db0 100644
--- a/channels/audin/client/sndio/audin_sndio.c
+++ b/channels/audin/client/sndio/audin_sndio.c
@@ -82,7 +82,7 @@ static void* audin_sndio_thread_func(void* arg)
struct sio_hdl* hdl;
struct sio_par par;
BYTE* buffer = NULL;
- size_t n, nbytes;
+ size_t n;
AudinSndioDevice* sndio = (AudinSndioDevice*)arg;
UINT error = 0;
DWORD status;
@@ -125,8 +125,11 @@ static void* audin_sndio_thread_func(void* arg)
goto err_out;
}
- nbytes =
- (sndio->FramesPerPacket * sndio->format.nChannels * (sndio->format.wBitsPerSample / 8));
+ const size_t nbytes = (1ull * sndio->FramesPerPacket * sndio->format.nChannels *
+ (sndio->format.wBitsPerSample / 8));
+ if (nbytes > INT32_MAX)
+ goto err_out;
+
buffer = (BYTE*)calloc((nbytes + sizeof(void*)), sizeof(BYTE));
if (buffer == NULL)
diff --git a/channels/audin/client/winmm/audin_winmm.c b/channels/audin/client/winmm/audin_winmm.c
index daa59254f..d6cceaf18 100644
--- a/channels/audin/client/winmm/audin_winmm.c
+++ b/channels/audin/client/winmm/audin_winmm.c
@@ -169,8 +169,6 @@ static BOOL test_format_supported(const PWAVEFORMATEX pwfx)
static DWORD WINAPI audin_winmm_thread_func(LPVOID arg)
{
AudinWinmmDevice* winmm = (AudinWinmmDevice*)arg;
- char* buffer = NULL;
- int size = 0;
WAVEHDR waveHdr[4] = { 0 };
DWORD status = 0;
MMRESULT rc = 0;
@@ -184,19 +182,22 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg)
return ERROR_INTERNAL_ERROR;
}
- size =
- (winmm->pwfx_cur->wBitsPerSample * winmm->pwfx_cur->nChannels * winmm->frames_per_packet +
- 7) /
- 8;
+ const size_t framesize =
+ 1ull * winmm->pwfx_cur->wBitsPerSample / 8ull * winmm->pwfx_cur->nChannels;
+ if (framesize > UINT32_MAX)
+ return ERROR_INTERNAL_ERROR;
+ const size_t size = framesize * winmm->frames_per_packet;
+ if (size > UINT32_MAX)
+ return ERROR_INTERNAL_ERROR;
for (int i = 0; i < 4; i++)
{
- buffer = (char*)malloc(size);
+ char* buffer = (char*)calloc(framesize, winmm->frames_per_packet);
if (!buffer)
return CHANNEL_RC_NO_MEMORY;
- waveHdr[i].dwBufferLength = size;
+ waveHdr[i].dwBufferLength = WINPR_ASSERTING_INT_CAST(DWORD, size);
waveHdr[i].dwFlags = 0;
waveHdr[i].lpData = buffer;
rc = waveInPrepareHeader(winmm->hWaveIn, &waveHdr[i], sizeof(waveHdr[i]));