]> sigrok.org Git - libsigrok.git/commitdiff
session: fix use after free of session->devs as reported by valgrind
authorStefan Brüns <redacted>
Thu, 26 Nov 2015 01:30:42 +0000 (02:30 +0100)
committerUwe Hermann <redacted>
Sun, 29 Nov 2015 00:13:58 +0000 (01:13 +0100)
==7478== Invalid write of size 8
==7478==    at 0x4E59182: sr_session_dev_remove_all (session.c:302)
==7478==    by 0x4E591CD: sr_session_destroy (session.c:265)
==7478==    by 0x4095D9: load_input_file_module (input.c:143)
==7478==    by 0x4097AB: load_input_file (input.c:157)
==7478==    by 0x40531E: main (main.c:288)
==7478==  Address 0x7877eb8 is 88 bytes inside a block of size 96 free'd
==7478==    at 0x4C2A37C: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==7478==    by 0x4E5F454: sr_input_free (input.c:573)
==7478==    by 0x4095C3: load_input_file_module (input.c:140)
==7478==    by 0x4097AB: load_input_file (input.c:157)
==7478==    by 0x40531E: main (main.c:288)

include/libsigrok/proto.h
src/device.c
src/session.c

index 069e7e840665f3499360f2c452fe599e95408d65..c2a8173f19d8f0b57708b55e85f3af1ac3f0028e 100644 (file)
@@ -111,6 +111,8 @@ SR_API int sr_session_destroy(struct sr_session *session);
 SR_API int sr_session_dev_remove_all(struct sr_session *session);
 SR_API int sr_session_dev_add(struct sr_session *session,
                struct sr_dev_inst *sdi);
+SR_API int sr_session_dev_remove(struct sr_session *session,
+               struct sr_dev_inst *sdi);
 SR_API int sr_session_dev_list(struct sr_session *session, GSList **devlist);
 SR_API int sr_session_trigger_set(struct sr_session *session, struct sr_trigger *trig);
 
index 537c89eff2ab353c167152de2af775a4317736a0..0eb86f4dee75ad66b05f31ba78b32ffcc39d1cba 100644 (file)
@@ -261,6 +261,9 @@ SR_PRIV void sr_dev_inst_free(struct sr_dev_inst *sdi)
        }
        g_slist_free(sdi->channel_groups);
 
+       if (sdi->session)
+               sr_session_dev_remove(sdi->session, sdi);
+
        g_free(sdi->vendor);
        g_free(sdi->model);
        g_free(sdi->version);
index f9df6e1f440411e8081d9fbef5498c75ab54a7de..6cf803dd3958f348e3985270707919256f3c209e 100644 (file)
@@ -403,6 +403,45 @@ SR_API int sr_session_dev_list(struct sr_session *session, GSList **devlist)
        return SR_OK;
 }
 
+/**
+ * Remove a device instance from a session.
+ *
+ * @param session The session to remove from. Must not be NULL.
+ * @param sdi The device instance to remove from a session. Must not
+ *            be NULL. Also, sdi->driver and sdi->driver->dev_open must
+ *            not be NULL.
+ *
+ * @retval SR_OK Success.
+ * @retval SR_ERR_ARG Invalid argument.
+ *
+ * @since 0.4.0
+ */
+SR_API int sr_session_dev_remove(struct sr_session *session,
+               struct sr_dev_inst *sdi)
+{
+       if (!sdi) {
+               sr_err("%s: sdi was NULL", __func__);
+               return SR_ERR_ARG;
+       }
+
+       if (!session) {
+               sr_err("%s: session was NULL", __func__);
+               return SR_ERR_ARG;
+       }
+
+       /* If sdi->session is not session, the device is not in this
+        * session. */
+       if (sdi->session != session) {
+               sr_err("%s: not assigned to this session", __func__);
+               return SR_ERR_ARG;
+       }
+
+       session->devs = g_slist_remove(session->devs, sdi);
+       sdi->session = NULL;
+
+       return SR_OK;
+}
+
 /**
  * Remove all datafeed callbacks in a session.
  *