OSDN Git Service

rawmidi: use snd_dlobj_cache_get2() in rawmidi open (coverity)
authorJaroslav Kysela <perex@perex.cz>
Fri, 24 May 2019 18:31:24 +0000 (20:31 +0200)
committerJaroslav Kysela <perex@perex.cz>
Fri, 24 May 2019 19:25:50 +0000 (21:25 +0200)
Use proper reference counting for the dynamic symbol.

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
include/local.h
src/dlmisc.c
src/rawmidi/rawmidi.c
src/rawmidi/rawmidi_local.h

index 5edad31..e8390df 100644 (file)
@@ -328,6 +328,8 @@ static inline int snd_open_device(const char *filename, int fmode)
 /* make local functions really local */
 #define snd_dlobj_cache_get \
        snd1_dlobj_cache_get
+#define snd_dlobj_cache_get2 \
+       snd1_dlobj_cache_get2
 #define snd_dlobj_cache_put \
        snd1_dlobj_cache_put
 #define snd_dlobj_cache_cleanup \
@@ -341,6 +343,7 @@ static inline int snd_open_device(const char *filename, int fmode)
 
 /* dlobj cache */
 void *snd_dlobj_cache_get(const char *lib, const char *name, const char *version, int verbose);
+void *snd_dlobj_cache_get2(const char *lib, const char *name, const char *version, int verbose);
 int snd_dlobj_cache_put(void *open_func);
 void snd_dlobj_cache_cleanup(void);
 
index 012e61b..8c8f3ff 100644 (file)
@@ -251,15 +251,15 @@ static inline void snd_dlobj_unlock(void) {}
 
 static LIST_HEAD(pcm_dlobj_list);
 
-void *snd_dlobj_cache_get(const char *lib, const char *name,
-                         const char *version, int verbose)
+static struct dlobj_cache *
+snd_dlobj_cache_get0(const char *lib, const char *name,
+                    const char *version, int verbose)
 {
        struct list_head *p;
        struct dlobj_cache *c;
        void *func, *dlobj;
        char errbuf[256];
 
-       snd_dlobj_lock();
        list_for_each(p, &pcm_dlobj_list) {
                c = list_entry(p, struct dlobj_cache, list);
                if (c->lib && lib && strcmp(c->lib, lib) != 0)
@@ -270,9 +270,7 @@ void *snd_dlobj_cache_get(const char *lib, const char *name,
                        continue;
                if (strcmp(c->name, name) == 0) {
                        c->refcnt++;
-                       func = c->func;
-                       snd_dlobj_unlock();
-                       return func;
+                       return c;
                }
        }
 
@@ -285,7 +283,6 @@ void *snd_dlobj_cache_get(const char *lib, const char *name,
                        SNDERR("Cannot open shared library %s (%s)",
                                                lib ? lib : "[builtin]",
                                                errbuf);
-               snd_dlobj_unlock();
                return NULL;
        }
 
@@ -314,6 +311,36 @@ void *snd_dlobj_cache_get(const char *lib, const char *name,
        c->dlobj = dlobj;
        c->func = func;
        list_add_tail(&c->list, &pcm_dlobj_list);
+       return c;
+}
+
+void *snd_dlobj_cache_get(const char *lib, const char *name,
+                         const char *version, int verbose)
+{
+       struct dlobj_cache *c;
+       void *func = NULL;
+
+       snd_dlobj_lock();
+       c = snd_dlobj_cache_get0(lib, name, version, verbose);
+       if (c)
+               func = c->func;
+       snd_dlobj_unlock();
+       return func;
+}
+
+void *snd_dlobj_cache_get2(const char *lib, const char *name,
+                          const char *version, int verbose)
+{
+       struct dlobj_cache *c;
+       void *func = NULL;
+
+       snd_dlobj_lock();
+       c = snd_dlobj_cache_get0(lib, name, version, verbose);
+       if (c) {
+               func = c->func;
+               /* double reference */
+               c->refcnt++;
+       }
        snd_dlobj_unlock();
        return func;
 }
index 2f41914..1b5f852 100644 (file)
@@ -162,7 +162,7 @@ static int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp
                                 snd_config_t *rawmidi_conf, int mode)
 {
        const char *str;
-       char buf[256], errbuf[256];
+       char buf[256];
        int err;
        snd_config_t *conf, *type_conf = NULL;
        snd_config_iterator_t i, next;
@@ -174,7 +174,6 @@ static int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp
 #ifndef PIC
        extern void *snd_rawmidi_open_symbols(void);
 #endif
-       void *h = NULL;
        if (snd_config_get_type(rawmidi_conf) != SND_CONFIG_TYPE_COMPOUND) {
                if (name)
                        SNDERR("Invalid type for RAWMIDI %s definition", name);
@@ -239,41 +238,37 @@ static int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp
 #ifndef PIC
        snd_rawmidi_open_symbols();
 #endif
-       h = INTERNAL(snd_dlopen)(lib, RTLD_NOW, errbuf, sizeof(errbuf));
-       if (h)
-               open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_RAWMIDI_DLSYM_VERSION));
-       err = 0;
-       if (!h) {
-               SNDERR("Cannot open shared library %s (%s)", lib, errbuf);
-               err = -ENOENT;
-       } else if (!open_func) {
-               SNDERR("symbol %s is not defined inside %s", open_name, lib);
-               snd_dlclose(h);
+       open_func = snd_dlobj_cache_get2(lib, open_name,
+                       SND_DLSYM_VERSION(SND_RAWMIDI_DLSYM_VERSION), 1);
+       if (!open_func) {
                err = -ENXIO;
+               goto _err;
        }
-       _err:
        if (type_conf)
                snd_config_delete(type_conf);
-       if (err >= 0)
-               err = open_func(inputp, outputp, name, rawmidi_root, rawmidi_conf, mode);
-       if (err < 0) {
-               if (h)
-                       snd_dlclose(h);
-               return err;
-       }
+       err = open_func(inputp, outputp, name, rawmidi_root, rawmidi_conf, mode);
+       if (err < 0)
+               goto _err;
        if (inputp) {
-               (*inputp)->dl_handle = h; h = NULL;
+               (*inputp)->open_func = open_func;
                snd_rawmidi_params_default(*inputp, &params);
                err = snd_rawmidi_params(*inputp, &params);
                assert(err >= 0);
        }
        if (outputp) {
-               (*outputp)->dl_handle = h;
+               (*outputp)->open_func = open_func;
                snd_rawmidi_params_default(*outputp, &params);
                err = snd_rawmidi_params(*outputp, &params);
                assert(err >= 0);
        }
        return 0;
+
+       _err:
+       if (open_func)
+               snd_dlobj_cache_put(open_func);
+       if (type_conf)
+               snd_config_delete(type_conf);
+       return err;
 }
 
 static int snd_rawmidi_open_noupdate(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
@@ -350,8 +345,8 @@ int snd_rawmidi_close(snd_rawmidi_t *rawmidi)
        assert(rawmidi);
        err = rawmidi->ops->close(rawmidi);
        free(rawmidi->name);
-       if (rawmidi->dl_handle)
-               snd_dlclose(rawmidi->dl_handle);
+       if (rawmidi->open_func)
+               snd_dlobj_cache_put(rawmidi->open_func);
        free(rawmidi);
        return err;
 }
index d76b35a..721e1ec 100644 (file)
@@ -37,7 +37,7 @@ typedef struct {
 } snd_rawmidi_ops_t;
 
 struct _snd_rawmidi {
-       void *dl_handle;
+       void *open_func;
        char *name;
        snd_rawmidi_type_t type;
        snd_rawmidi_stream_t stream;