]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
[core] avoid overflow when channel muxing
authorDragos Oancea <dragos@signalwire.com>
Fri, 17 Jan 2020 20:58:57 +0000 (20:58 +0000)
committerAndrey Volk <andywolk@gmail.com>
Fri, 17 Jan 2020 20:58:57 +0000 (00:58 +0400)
src/switch_core_file.c
tests/unit/switch_core_file.c

index 717233ce55f6ce0024067e9da76ca8bfb3595e88..fb6f453a43e88fc5544e58a42870ea4d4f4562a8 100644 (file)
@@ -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);
index 34edf7d7c0d04709105f1d798be24e2c385181bd..3515e6787dd842e059b5a00e7e5379622d499e3c 100644 (file)
@@ -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()
 }