From 97a0b0fbaea0e98e973e0e3ca69ebdea0a0f61e8 Mon Sep 17 00:00:00 2001
From: Dragos Oancea <dragos@signalwire.com>
Date: Fri, 13 Mar 2020 18:42:43 +0000
Subject: [PATCH] [mod_opusfile] protect ogg data buff

---
 src/mod/formats/mod_opusfile/mod_opusfile.c       |  7 ++++---
 src/mod/formats/mod_opusfile/test/test_opusfile.c | 11 +++++++++--
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/src/mod/formats/mod_opusfile/mod_opusfile.c b/src/mod/formats/mod_opusfile/mod_opusfile.c
index ea932ed0ff..38f5d1f442 100644
--- a/src/mod/formats/mod_opusfile/mod_opusfile.c
+++ b/src/mod/formats/mod_opusfile/mod_opusfile.c
@@ -976,6 +976,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[OGG/OPUS Stream Decode] read_stream_thread(): switch_thread_self(): 0x%lx\n",  switch_thread_self());
 	}
 	switch_thread_rwlock_rdlock(context->rwlock);
+	switch_mutex_lock(context->ogg_mutex);
 
 	if ((buffered_ogg_bytes = switch_buffer_inuse(context->ogg_buffer))) {
 		if (buffered_ogg_bytes <= OGG_MAX_PAGE_SIZE) {
@@ -1021,6 +1022,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
 		}
 	}
 
+	switch_mutex_unlock(context->ogg_mutex);
 	switch_thread_rwlock_unlock(context->rwlock);
 	return NULL;
 }
@@ -1071,9 +1073,9 @@ static switch_status_t switch_opusstream_decode(switch_codec_t *codec,
 #endif
 
 	switch_thread_rwlock_rdlock(context->rwlock);
+	switch_mutex_lock(context->ogg_mutex);
 	memset(context->ogg_data, 0, sizeof(context->ogg_data)); 
 	if (encoded_data_len <= SWITCH_RECOMMENDED_BUFFER_SIZE) {
-		switch_mutex_lock(context->ogg_mutex);
 		switch_buffer_write(context->ogg_buffer, encode_buf, encoded_data_len);
  
 		if ((buffered_ogg_bytes = switch_buffer_inuse(context->ogg_buffer)) >= ogg_bytes) {
@@ -1089,12 +1091,10 @@ static switch_status_t switch_opusstream_decode(switch_codec_t *codec,
 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[OGG/OPUS Stream Decode] buffered ogg data bigger than max OGG page size, will flush\n");
 				*decoded_data_len = 0;
 				switch_buffer_zero(context->ogg_buffer);
-				switch_mutex_unlock(context->ogg_mutex);
 				switch_goto_status(SWITCH_STATUS_SUCCESS, end);
 			}
 		}
 
-		switch_mutex_unlock(context->ogg_mutex);
 	} else {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "[OGG/OPUS Stream Decode] too much data to buffer, flushing buffer!\n");
 		*decoded_data_len = 0;
@@ -1134,6 +1134,7 @@ static switch_status_t switch_opusstream_decode(switch_codec_t *codec,
 end:
 
 	switch_thread_rwlock_unlock(context->rwlock);
+	switch_mutex_unlock(context->ogg_mutex);
 	return status;
 }
 
diff --git a/src/mod/formats/mod_opusfile/test/test_opusfile.c b/src/mod/formats/mod_opusfile/test/test_opusfile.c
index f21738bdb7..feb74619e5 100644
--- a/src/mod/formats/mod_opusfile/test/test_opusfile.c
+++ b/src/mod/formats/mod_opusfile/test/test_opusfile.c
@@ -170,6 +170,7 @@ FST_CORE_BEGIN(".")
 			uint32_t decoded_len;
 			size_t write_len;
 			unsigned char decbuf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };
+			switch_stream_handle_t stream = { 0 };
 #ifdef  HAVE_OPUSFILE_ENCODE
 			switch_file_handle_t fh = { 0 };
 			unsigned char encbuf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };
@@ -216,6 +217,12 @@ FST_CORE_BEGIN(".")
 			&codec_settings, fst_pool);
 			fst_check(status == SWITCH_STATUS_SUCCESS);
 
+			SWITCH_STANDARD_STREAM(stream);
+
+			switch_api_execute("opusfile_debug", "on", NULL, &stream);
+
+			switch_safe_free(stream.data);
+
 #ifdef HAVE_OPUSFILE_ENCODE
 			status = switch_core_codec_init(&write_codec,
 			"OPUSSTREAM",
@@ -277,12 +284,12 @@ FST_CORE_BEGIN(".")
 
 			fhw.native_rate = filerate;
 
-			flen = OGG_MIN_PAGE_SIZE;
+			flen = 4096;
 			while (switch_file_read(fd, &buf, &flen) == SWITCH_STATUS_SUCCESS || flen != 0) {
 				status = SWITCH_STATUS_SUCCESS;
 				while (status == SWITCH_STATUS_SUCCESS) {
 					status = switch_core_codec_decode(&read_codec, NULL, &buf, flen, filerate, &decbuf, &decoded_len, &rate, &flags);
-					fst_requires(status == SWITCH_STATUS_SUCCESS);
+					fst_check(status == SWITCH_STATUS_SUCCESS);
 					write_len = decoded_len / sizeof(int16_t);
 					if (write_len) switch_core_file_write(&fhw, &decbuf, &write_len);
 					else break;