From e2d435dad669009f4e0dc7dd359a1d72719078c2 Mon Sep 17 00:00:00 2001
From: Tom M <tom.mbrt@googlemail.com>
Date: Thu, 30 Apr 2020 19:49:58 +0200
Subject: [PATCH] Fix a NULL deref in delete_rvoice_mixer_threads() (#641)

The function attempts to lock a mutex that might have not been created yet, due to a previous error.
---
 src/rvoice/fluid_rvoice_mixer.c | 42 +++++++++++++++++++--------------
 1 file changed, 24 insertions(+), 18 deletions(-)

diff --git a/src/rvoice/fluid_rvoice_mixer.c b/src/rvoice/fluid_rvoice_mixer.c
index 463b9806..4f691198 100644
--- a/src/rvoice/fluid_rvoice_mixer.c
+++ b/src/rvoice/fluid_rvoice_mixer.c
@@ -728,9 +728,9 @@ new_fluid_rvoice_mixer(int buf_count, int fx_buf_count, int fx_units, fluid_real
         FLUID_LOG(FLUID_ERR, "Out of memory");
         goto error_recovery;
     }
-    
+
     FLUID_MEMSET(mixer->fx, 0, fx_units * sizeof(*mixer->fx));
-    
+
     for(i = 0; i < fx_units; i++)
     {
         mixer->fx[i].reverb = new_fluid_revmodel(sample_rate);
@@ -768,7 +768,7 @@ new_fluid_rvoice_mixer(int buf_count, int fx_buf_count, int fx_units, fluid_real
 #endif
 
     return mixer;
-    
+
 error_recovery:
     delete_fluid_rvoice_mixer(mixer);
     return NULL;
@@ -1266,27 +1266,33 @@ fluid_render_loop_multithread(fluid_rvoice_mixer_t *mixer, int current_blockcoun
 static void delete_rvoice_mixer_threads(fluid_rvoice_mixer_t *mixer)
 {
     int i;
-    fluid_atomic_int_set(&mixer->threads_should_terminate, 1);
-    // Signal threads to wake up
-    fluid_cond_mutex_lock(mixer->wakeup_threads_m);
 
-    for(i = 0; i < mixer->thread_count; i++)
+    // if no threads have been created yet (e.g. because a previous error prevented creation of threads
+    // mutexes and condition variables), skip terminating threads
+    if(mixer->thread_count != 0)
     {
-        fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_TERMINATE);
-    }
+        fluid_atomic_int_set(&mixer->threads_should_terminate, 1);
+        // Signal threads to wake up
+        fluid_cond_mutex_lock(mixer->wakeup_threads_m);
 
-    fluid_cond_broadcast(mixer->wakeup_threads);
-    fluid_cond_mutex_unlock(mixer->wakeup_threads_m);
-
-    for(i = 0; i < mixer->thread_count; i++)
-    {
-        if(mixer->threads[i].thread)
+        for(i = 0; i < mixer->thread_count; i++)
         {
-            fluid_thread_join(mixer->threads[i].thread);
-            delete_fluid_thread(mixer->threads[i].thread);
+            fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_TERMINATE);
         }
 
-        fluid_mixer_buffers_free(&mixer->threads[i]);
+        fluid_cond_broadcast(mixer->wakeup_threads);
+        fluid_cond_mutex_unlock(mixer->wakeup_threads_m);
+
+        for(i = 0; i < mixer->thread_count; i++)
+        {
+            if(mixer->threads[i].thread)
+            {
+                fluid_thread_join(mixer->threads[i].thread);
+                delete_fluid_thread(mixer->threads[i].thread);
+            }
+
+            fluid_mixer_buffers_free(&mixer->threads[i]);
+        }
     }
 
     FLUID_FREE(mixer->threads);