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)
+static void srd_decoder_unload_cb(void *arg, void *ignored)
+{
+ (void)ignored;
+
+ srd_decoder_unload((struct srd_decoder *)arg);
+}
+
/**
* Unload all loaded protocol decoders.
*
/**
* Unload all loaded protocol decoders.
*
*/
SRD_API int srd_decoder_unload_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;
g_slist_free(pd_list);
pd_list = NULL;
+static void srd_session_destroy_cb(void *arg, void *ignored)
+{
+ (void)ignored; // Prevent unused warning
+ srd_session_destroy((struct srd_session *)arg);
+}
+
/**
* Shutdown libsigrokdecode.
*
/**
* Shutdown libsigrokdecode.
*
{
srd_dbg("Exiting libsigrokdecode.");
{
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);
srd_decoder_unload_all();
g_slist_free_full(searchpaths, g_free);