From: Stefan BrĂ¼ns Date: Thu, 26 Nov 2015 01:30:42 +0000 (+0100) Subject: session: fix use after free of session->devs as reported by valgrind X-Git-Tag: libsigrok-0.4.0~95 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=fe7b8efc6b36aa707365f1d23c645303a5f2307a;p=libsigrok.git session: fix use after free of session->devs as reported by valgrind ==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) --- diff --git a/include/libsigrok/proto.h b/include/libsigrok/proto.h index 069e7e84..c2a8173f 100644 --- a/include/libsigrok/proto.h +++ b/include/libsigrok/proto.h @@ -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); diff --git a/src/device.c b/src/device.c index 537c89ef..0eb86f4d 100644 --- a/src/device.c +++ b/src/device.c @@ -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); diff --git a/src/session.c b/src/session.c index f9df6e1f..6cf803dd 100644 --- a/src/session.c +++ b/src/session.c @@ -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. *