From c2e80ea1e305c00cd07ab867ac9f04d4663cc836 Mon Sep 17 00:00:00 2001 From: Dragos Oancea Date: Fri, 17 Jan 2020 20:58:57 +0000 Subject: [PATCH] [core] avoid overflow when channel muxing --- src/switch_core_file.c | 8 +++-- tests/unit/switch_core_file.c | 58 +++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/switch_core_file.c b/src/switch_core_file.c index 717233ce55..fb6f453a43 100644 --- a/src/switch_core_file.c +++ b/src/switch_core_file.c @@ -589,15 +589,17 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_write(switch_file_handle_t *fh, if (fh->real_channels != fh->channels && !switch_test_flag(fh, SWITCH_FILE_NOMUX)) { - int need = *len * 2 * fh->real_channels; + int need = *len * 2 * (fh->real_channels > fh->channels ? fh->real_channels : fh->channels); if (need > fh->muxlen) { fh->muxbuf = realloc(fh->muxbuf, need); switch_assert(fh->muxbuf); fh->muxlen = need; - memcpy(fh->muxbuf, data, fh->muxlen); - data = fh->muxbuf; + } + if (fh->muxbuf) { + memcpy(fh->muxbuf, data, *len * 2); + data = fh->muxbuf; } switch_mux_channels((int16_t *) data, *len, fh->real_channels, fh->channels); diff --git a/tests/unit/switch_core_file.c b/tests/unit/switch_core_file.c index 34edf7d7c0..3515e6787d 100644 --- a/tests/unit/switch_core_file.c +++ b/tests/unit/switch_core_file.c @@ -127,6 +127,64 @@ FST_CORE_BEGIN("./conf") } FST_TEST_END() + FST_TEST_BEGIN(test_switch_core_file_write_mono) + { + switch_status_t status = SWITCH_STATUS_FALSE; + switch_file_handle_t fhw = { 0 }; + static char filename[] = "/tmp/fs_write_unit_test.wav"; + char *buf; + int nr_frames = 3, i; + switch_size_t len; + + len = 160; + switch_malloc(buf, len * sizeof(int16_t)); + + status = switch_core_file_open(&fhw, filename, 1, 8000, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT, NULL); + fst_check(status == SWITCH_STATUS_SUCCESS); + + for (i = 0; i < nr_frames; i++) { + memset(buf, i, len * sizeof(int16_t)); + switch_core_file_write(&fhw, buf, &len); + } + + status = switch_core_file_close(&fhw); + fst_check(status == SWITCH_STATUS_SUCCESS); + + switch_safe_free(buf); + unlink(filename); + } + FST_TEST_END() + FST_TEST_BEGIN(test_switch_core_file_write_mono_to_stereo) + { + switch_status_t status = SWITCH_STATUS_FALSE; + switch_file_handle_t fhw = { 0 }; + static char filename[] = "/tmp/fs_write_unit_test.wav"; + char *buf; + int nr_frames = 3, i, want_channels = 2; + switch_size_t len; + + len = 160; + switch_malloc(buf, len * sizeof(int16_t)); + + status = switch_core_file_open(&fhw, filename, want_channels, 8000, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT, NULL); + fst_check(status == SWITCH_STATUS_SUCCESS); + + fhw.real_channels = 1; + + for (i = 0; i < nr_frames; i++) { + memset(buf, i, len * sizeof(int16_t)); + status = switch_core_file_write(&fhw, buf, &len); + fst_requires(status == SWITCH_STATUS_SUCCESS); + } + + status = switch_core_file_close(&fhw); + fst_check(status == SWITCH_STATUS_SUCCESS); + + switch_safe_free(buf); + unlink(filename); + + } + FST_TEST_END() } FST_SUITE_END() }