Fix bad memory accesses during srd_exit()
authorJon Burgess <jburgess777@gmail.com>
Sun, 14 Oct 2018 17:49:52 +0000 (18:49 +0100)
committerUwe Hermann <uwe@hermann-uwe.de>
Sun, 21 Oct 2018 14:39:33 +0000 (16:39 +0200)
When the decoder and session unload functions are called they
remove themselves from the list. The code walking the list
must be careful to avoid accessing the next pointer which
might now be invalid. The g_slist_foreach() takes care of
this.

Reports from Valgrind before fix:

==175436== Invalid read of size 8
--
==175436==  Address 0xe3f2598 is 8 bytes inside a block of size 16 free'd
==175436==    at 0x4C2FDAC: free (vg_replace_malloc.c:530)
==175436==    by 0x563C541: g_free (in /usr/lib64/libglib-2.0.so.0.5600.3)
==175436==    by 0x5654783: g_slice_free1 (in /usr/lib64/libglib-2.0.so.0.5600.3)
==175436==    by 0x56552A2: g_slist_remove (in /usr/lib64/libglib-2.0.so.0.5600.3)
==175436==    by 0x4E3FEFF: srd_session_destroy (session.c:343)
==175436==    by 0x4E3F5C7: srd_exit (srd.c:311)
==175436==    by 0x40336F: test_inst_new (inst.c:40)
==175436==    by 0x53E51D5: srunner_run_tagged (in /usr/lib64/libcheck.so.0.0.0)
==175436==    by 0x401237: main (main.c:51)
==175436==  Block was alloc'd at
==175436==    at 0x4C2EBAB: malloc (vg_replace_malloc.c:299)
==175436==    by 0x563C435: g_malloc (in /usr/lib64/libglib-2.0.so.0.5600.3)
==175436==    by 0x5654056: g_slice_alloc (in /usr/lib64/libglib-2.0.so.0.5600.3)
==175436==    by 0x5655797: g_slist_append (in /usr/lib64/libglib-2.0.so.0.5600.3)
==175436==    by 0x4E3FC75: srd_session_new (session.c:71)
==175436==    by 0x403345: test_inst_new (inst.c:37)
==175436==    by 0x53E51D5: srunner_run_tagged (in /usr/lib64/libcheck.so.0.0.0)
==175436==    by 0x401237: main (main.c:51)

decoder.c
srd.c

index 7374b779453e015025b59ae6dc4b5f16e5416e09..260f6367787597bc8f9c5818bf362f574b9b1c81 100644 (file)
--- a/decoder.c
+++ b/decoder.c
@@ -1068,6 +1068,13 @@ SRD_API int srd_decoder_load_all(void)
        return SRD_OK;
 }
 
+static void srd_decoder_unload_cb(void *arg, void *ignored)
+{
+       (void)ignored;
+
+       srd_decoder_unload((struct srd_decoder *)arg);
+}
+
 /**
  * Unload all loaded protocol decoders.
  *
@@ -1077,8 +1084,7 @@ SRD_API int srd_decoder_load_all(void)
  */
 SRD_API int srd_decoder_unload_all(void)
 {
-       for (GSList *l = pd_list; l; l = l->next)
-               srd_decoder_unload(l->data);
+       g_slist_foreach(pd_list, srd_decoder_unload_cb, NULL);
        g_slist_free(pd_list);
        pd_list = NULL;
 
diff --git a/srd.c b/srd.c
index 535ea122e5b3876d0846e170d5af63a2f6ca746c..248d8e5a69e3793450f50127a47e8a7563b416e0 100644 (file)
--- a/srd.c
+++ b/srd.c
@@ -289,6 +289,12 @@ SRD_API int srd_init(const char *path)
        return SRD_OK;
 }
 
+static void srd_session_destroy_cb(void *arg, void *ignored)
+{
+       (void)ignored; // Prevent unused warning
+       srd_session_destroy((struct srd_session *)arg);
+}
+
 /**
  * Shutdown libsigrokdecode.
  *
@@ -307,8 +313,9 @@ SRD_API int srd_exit(void)
 {
        srd_dbg("Exiting libsigrokdecode.");
 
-       for (GSList *l = sessions; l; l = l->next)
-               srd_session_destroy(l->data);
+       g_slist_foreach(sessions, srd_session_destroy_cb, NULL);
+       g_slist_free(sessions);
+       sessions = NULL;
 
        srd_decoder_unload_all();
        g_slist_free_full(searchpaths, g_free);