From: Jaroslav Kysela Date: Fri, 24 May 2019 18:31:24 +0000 (+0200) Subject: rawmidi: use snd_dlobj_cache_get2() in rawmidi open (coverity) X-Git-Tag: v1.2.1~61 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=8ab0393b42e08655a5fee0a8e84b3ba84932465b;p=alsa-lib.git rawmidi: use snd_dlobj_cache_get2() in rawmidi open (coverity) Use proper reference counting for the dynamic symbol. Signed-off-by: Jaroslav Kysela --- diff --git a/include/local.h b/include/local.h index 5edad317..e8390df5 100644 --- a/include/local.h +++ b/include/local.h @@ -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); diff --git a/src/dlmisc.c b/src/dlmisc.c index 012e61bc..8c8f3ff7 100644 --- a/src/dlmisc.c +++ b/src/dlmisc.c @@ -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; } diff --git a/src/rawmidi/rawmidi.c b/src/rawmidi/rawmidi.c index 2f419142..1b5f8525 100644 --- a/src/rawmidi/rawmidi.c +++ b/src/rawmidi/rawmidi.c @@ -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, ¶ms); err = snd_rawmidi_params(*inputp, ¶ms); assert(err >= 0); } if (outputp) { - (*outputp)->dl_handle = h; + (*outputp)->open_func = open_func; snd_rawmidi_params_default(*outputp, ¶ms); err = snd_rawmidi_params(*outputp, ¶ms); 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; } diff --git a/src/rawmidi/rawmidi_local.h b/src/rawmidi/rawmidi_local.h index d76b35a3..721e1ec9 100644 --- a/src/rawmidi/rawmidi_local.h +++ b/src/rawmidi/rawmidi_local.h @@ -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;