From f55eece85c367558cc770538b1e2414ebc615e38 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 7 Jan 2026 17:41:03 +0100 Subject: [PATCH 01/14] error: return old snd_lib_error_set_handler() behaviour Unfortunately, the case when the old application sets own error callback using the old method, was not handled properly in snd_lib_vlog_default() function. Make sure that only error messages are passed to this old callback and silent other log priorities. Link: https://bugs.gentoo.org/968131 Signed-off-by: Jaroslav Kysela --- src/error.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/error.c b/src/error.c index e575f2eb..1cb8a579 100644 --- a/src/error.c +++ b/src/error.c @@ -34,6 +34,8 @@ #include #include +static void snd_lib_error_default(const char *file, int line, const char *function, int errcode, const char *fmt, ...); + /** * Array of error codes in US ASCII. */ @@ -317,6 +319,12 @@ static void snd_lib_vlog_default(int prio, int interface, const char *file, int local_error(file, line, function, errcode, fmt, arg); return; } + if (snd_lib_error != snd_lib_error_default) { + if (prio == SND_LOG_ERROR) + snd_lib_error(file, line, function, errcode, fmt, arg); + /* ignore other priorities - restore old behaviour */ + return; + } if (!snd_lib_log_filter(prio, interface, NULL)) return; From a37b8b9377676327016c2335facdce66d9d8700c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 7 Jan 2026 17:45:24 +0100 Subject: [PATCH 02/14] error: fix indendation in snd_lib_log_filter() Signed-off-by: Jaroslav Kysela --- src/error.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/error.c b/src/error.c index 1cb8a579..ae54b598 100644 --- a/src/error.c +++ b/src/error.c @@ -283,7 +283,8 @@ int snd_lib_log_filter(int prio, int interface, const char *configstr) if (interface > 0 && interface <= SND_ILOG_LAST && debug_config.interface_levels[interface] > 0) { level = debug_config.interface_levels[interface]; } else { - level = debug_config.global_level; } + level = debug_config.global_level; + } if (level == 0) level = SND_LOG_ERROR; From 8bea4b13d162386e5dbd28371a4491426672a7df Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 8 Jan 2026 13:19:34 +0100 Subject: [PATCH 03/14] error: fix the "return old snd_lib_error_set_handler() behaviour" The variable arguments must be handled differently. Add a conversion routine which use the original argument call convention. Fixes: f55eece8 ("error: return old snd_lib_error_set_handler() behaviour") Signed-off-by: Jaroslav Kysela --- src/error.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/error.c b/src/error.c index ae54b598..df8ba522 100644 --- a/src/error.c +++ b/src/error.c @@ -293,6 +293,8 @@ int snd_lib_log_filter(int prio, int interface, const char *configstr) return prio <= (int)level; } +static void snd_lib_error_vdefault(const char *file, int line, const char *function, int errcode, const char *fmt, va_list arg); + /** * \brief The default log handler function. * \param prio Priority value (SND_LOG_*). @@ -322,7 +324,7 @@ static void snd_lib_vlog_default(int prio, int interface, const char *file, int } if (snd_lib_error != snd_lib_error_default) { if (prio == SND_LOG_ERROR) - snd_lib_error(file, line, function, errcode, fmt, arg); + snd_lib_error_vdefault(file, line, function, errcode, fmt, arg); /* ignore other priorities - restore old behaviour */ return; } @@ -452,6 +454,25 @@ static void snd_lib_error_default(const char *file, int line, const char *functi va_end(arg); } +/** + * \brief The default error handler function. + * \param file The filename where the error was hit. + * \param line The line number. + * \param function The function name. + * \param errcode The error code. + * \param fmt The message (including the format characters). + * \param arg Optional arguments. + * \deprecated Since 1.2.15 + * + * Use snd_lib_vlog handler to print error message for anonymous interface. + */ +static void snd_lib_error_vdefault(const char *file, int line, const char *function, int errcode, const char *fmt, va_list arg) +{ + char msg[512]; + vsnprintf(msg, sizeof(msg), fmt, arg); + snd_lib_error(file, line, function, errcode, "%s", msg); +} + /** * \ingroup Error * \deprecated Since 1.2.15 From 50b532de795c6342bdf0aaf7b327526a6a0aa042 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 8 Jan 2026 13:56:48 +0100 Subject: [PATCH 04/14] ucm: add some traces for the config filenames It is handy to see the path names in the loading chain. Signed-off-by: Jaroslav Kysela --- src/ucm/parser.c | 2 ++ src/ucm/utils.c | 1 + 2 files changed, 3 insertions(+) diff --git a/src/ucm/parser.c b/src/ucm/parser.c index a76be776..60861213 100644 --- a/src/ucm/parser.c +++ b/src/ucm/parser.c @@ -3417,6 +3417,7 @@ static int parse_toplevel_path(snd_use_case_mgr_t *uc_mgr, } ucm_filename(fn, sizeof(fn), version, dir, file); + snd_trace(UCM, "probing configuration file '%s'", fn); if (access(fn, R_OK) == 0 && lstat64(fn, &st) == 0) { if (S_ISLNK(st.st_mode)) { ssize_t r; @@ -3448,6 +3449,7 @@ static int parse_toplevel_path(snd_use_case_mgr_t *uc_mgr, } free(link); } + snd_trace(UCM, "using directory '%s' and file '%s'", dir, file); if (replace_string(&uc_mgr->conf_dir_name, dir) == NULL) goto __enomem; if (replace_string(&uc_mgr->conf_file_name, file) == NULL) diff --git a/src/ucm/utils.c b/src/ucm/utils.c index 68a7521e..dcb5c6e1 100644 --- a/src/ucm/utils.c +++ b/src/ucm/utils.c @@ -364,6 +364,7 @@ int uc_mgr_config_load_into(int format, const char *file, snd_config_t *top) const char *default_paths[2]; int err; + snd_trace(UCM, "loading config '%s'", file); fp = fopen(file, "r"); if (!fp) { err = -errno; From b3bc2b4feee7a97db919b4c842b329f24563718c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 8 Jan 2026 14:49:58 +0100 Subject: [PATCH 05/14] Makefile: remove dist-hook and remove tar option 'follow symlinks' The dist-hook is not required for latest automake. It was introduced in 2000, so the things were hopefully fixed now. Signed-off-by: Jaroslav Kysela --- Makefile.am | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/Makefile.am b/Makefile.am index 5bcef999..ded3afc7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,6 @@ +# remove -h for tar (follow symlinks) to avoid endless include/alsa/alsa/... +am__tar = $${TAR-tar} cof - "$$tardir" + ACLOCAL_AMFLAGS = -I m4 SUBDIRS=doc include src @@ -20,14 +23,6 @@ AM_CPPFLAGS=-I$(top_srcdir)/include rpm: dist $(MAKE) -C utils rpm -dist-hook: - -chmod -R a+r $(distdir) - @if ! test -z "$(AMTAR)"; then \ - $(AMTAR) --create --verbose --file=- $(distdir) | bzip2 -c -9 > $(distdir).tar.bz2 ; \ - else \ - $(TAR) --create --verbose --file=- $(distdir) | bzip2 -c -9 > $(distdir).tar.bz2 ; \ - fi - doc-dummy: doc: doc-dummy From 63a981865a1c7d9501ae556e28ae3bb53d015b61 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 8 Jan 2026 15:27:57 +0100 Subject: [PATCH 06/14] Release v1.2.15.2 Signed-off-by: Jaroslav Kysela --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 232cce1b..4537c609 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) -AC_INIT(alsa-lib, 1.2.15.1) +AC_INIT(alsa-lib, 1.2.15.2) AC_CONFIG_SRCDIR([src/control/control.c]) AC_CONFIG_MACRO_DIR([m4]) From 805464c7bd40a14e1f0e8ab8339d5cf5a2398d91 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 13 Jan 2026 08:09:47 +0100 Subject: [PATCH 07/14] seq: return back old snd_seq_drain_output behaviour for -EAGAIN It seems that many applications did not follow the documentation including pyalsa sequencer module, thus return the previous behaviour and correct documentation. Closes: https://github.com/alsa-project/alsa-lib/issues/493 Fixes: b97a11ec ("seq: fix snd_seq_drain_output return value for partial drain") Signed-off-by: Jaroslav Kysela --- src/seq/seq.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/seq/seq.c b/src/seq/seq.c index 49f013e0..b9d9c041 100644 --- a/src/seq/seq.c +++ b/src/seq/seq.c @@ -4431,8 +4431,7 @@ int snd_seq_event_output_pending(snd_seq_t *seq) * \brief drain output buffer to sequencer * \param seq sequencer handle * \return 0 when all events are drained and sent to sequencer. - * When events still remain on the buffer, the byte size of remaining - * events are returned. On error a negative error code is returned. + * On error a negative error code is returned (including -EAGAIN). * * This function drains all pending events on the output buffer. * The function returns immediately after the events are sent to the queues @@ -4444,19 +4443,15 @@ int snd_seq_event_output_pending(snd_seq_t *seq) */ int snd_seq_drain_output(snd_seq_t *seq) { - ssize_t result, processed = 0; + ssize_t result; assert(seq); while (seq->obufused > 0) { result = seq->ops->write(seq, seq->obuf, seq->obufused); - if (result < 0) { - if (result == -EAGAIN && processed > 0) - return seq->obufused; + if (result < 0) return result; - } if ((size_t)result < seq->obufused) memmove(seq->obuf, seq->obuf + result, seq->obufused - result); seq->obufused -= result; - processed += result; } return 0; } From 75ed5f05babcae7515aff5277e038ffd854c7669 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 13 Jan 2026 08:12:40 +0100 Subject: [PATCH 08/14] Release v1.2.15.3 Signed-off-by: Jaroslav Kysela --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 4537c609..9810fd4a 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) -AC_INIT(alsa-lib, 1.2.15.2) +AC_INIT(alsa-lib, 1.2.15.3) AC_CONFIG_SRCDIR([src/control/control.c]) AC_CONFIG_MACRO_DIR([m4]) From 7887fbc6f0f660072d1405231703985b72d40cf1 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 26 Jan 2026 15:08:54 +0100 Subject: [PATCH 09/14] ucm: libconfig parser - fix pathname for substituted file The path name substituted file contents and normal file contents should be handled similary. Use correct function determining the right base directory name. Fixes: 8f5779eb ("ucm: add LibraryConfig support") Signed-off-by: Jaroslav Kysela --- src/ucm/parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ucm/parser.c b/src/ucm/parser.c index 60861213..baa19144 100644 --- a/src/ucm/parser.c +++ b/src/ucm/parser.c @@ -804,7 +804,7 @@ static int parse_libconfig1(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg) if (file) { if (substfile) { snd_config_t *cfg; - err = uc_mgr_config_load(uc_mgr->conf_format, file, &cfg); + err = uc_mgr_config_load_file(uc_mgr, file, &cfg); if (err < 0) return err; err = uc_mgr_substitute_tree(uc_mgr, cfg); From bc332f4211af98054e7c64aabbe59c7a16ac4e36 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 29 Jan 2026 15:33:45 +0100 Subject: [PATCH 10/14] control: ctlparse - make numid parsing more robust Also correct the last amixer stderr printf to snd_error(). Signed-off-by: Jaroslav Kysela --- src/control/ctlparse.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/control/ctlparse.c b/src/control/ctlparse.c index b23234d7..3bd86435 100644 --- a/src/control/ctlparse.c +++ b/src/control/ctlparse.c @@ -156,8 +156,10 @@ char *snd_ctl_ascii_elem_id_get(snd_ctl_elem_id_t *id) int __snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str, const char **ret_ptr) { - int c, size, numid; + char buf[64]; + int c, size; int err = -EINVAL; + long l; char *ptr; while (isspace(*str)) @@ -168,12 +170,23 @@ int __snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str, while (*str) { if (!strncasecmp(str, "numid=", 6)) { str += 6; - numid = atoi(str); - if (numid <= 0) { - fprintf(stderr, "amixer: Invalid numid %d\n", numid); + ptr = buf; + size = 0; + while (*str && *str != ',') { + if (size < (int)sizeof(buf)) { + *ptr++ = *str; + size++; + } + str++; + } + *ptr = '\0'; + if (safe_strtol(buf, &l) < 0) + l = -1; + if (l <= 0 || l >= INT32_MAX) { + snd_error(CONTROL, "Invalid numid %ld (%s)", l, buf); goto out; } - snd_ctl_elem_id_set_numid(dst, atoi(str)); + snd_ctl_elem_id_set_numid(dst, (int)l); while (isdigit(*str)) str++; } else if (!strncasecmp(str, "iface=", 6)) { @@ -200,7 +213,6 @@ int __snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str, goto out; } } else if (!strncasecmp(str, "name=", 5)) { - char buf[64]; str += 5; ptr = buf; size = 0; From 5f7fe33002d2d98d84f72e381ec2cccc0d5d3d40 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 29 Jan 2026 16:51:09 +0100 Subject: [PATCH 11/14] topology: decoder - add boundary check for channel mixer count Malicious binary topology file may cause heap corruption. CVE: CVE-2026-25068 Signed-off-by: Jaroslav Kysela --- src/topology/ctl.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/topology/ctl.c b/src/topology/ctl.c index a0c24518..322c461c 100644 --- a/src/topology/ctl.c +++ b/src/topology/ctl.c @@ -1250,6 +1250,11 @@ int tplg_decode_control_mixer1(snd_tplg_t *tplg, if (mc->num_channels > 0) { map = tplg_calloc(heap, sizeof(*map)); map->num_channels = mc->num_channels; + if (map->num_channels > SND_TPLG_MAX_CHAN || + map->num_channels > SND_SOC_TPLG_MAX_CHAN) { + snd_error(TOPOLOGY, "mixer: unexpected channel count %d", map->num_channels); + return -EINVAL; + } for (i = 0; i < map->num_channels; i++) { map->channel[i].reg = mc->channel[i].reg; map->channel[i].shift = mc->channel[i].shift; From 166407dae4c91583aff43624ce1eafb8695a4482 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 3 Feb 2026 17:46:02 +0100 Subject: [PATCH 12/14] control: remap - fix numid lookup issue The 'amixer controls' and 'amixer cget numid=' combo was not working correctly when the remapping was active. This assert was trigerred: amixer: control.c:427: snd_ctl_elem_info: Assertion `ctl && info && (info->id.name[0] || info->id.numid)' failed All elements must be loaded and mapping created to build the numid -> fullid link. Signed-off-by: Jaroslav Kysela --- src/control/control_remap.c | 79 ++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 10 deletions(-) diff --git a/src/control/control_remap.c b/src/control/control_remap.c index 7d90d7ad..f7f118aa 100644 --- a/src/control/control_remap.c +++ b/src/control/control_remap.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -97,8 +98,11 @@ typedef struct { typedef struct { snd_ctl_t *child; - int numid_remap_active; + bool list_complete; + bool numid_remap_active; unsigned int numid_app_last; + unsigned int list_first; + unsigned int list_last; size_t numid_items; size_t numid_alloc; @@ -125,6 +129,8 @@ typedef struct { } snd_ctl_remap_t; #endif +static int remap_load_list(snd_ctl_remap_t *priv); + static snd_ctl_numid_t *remap_numid_temp(snd_ctl_remap_t *priv, unsigned int numid) { priv->numid_temp.numid_child = numid; @@ -137,6 +143,8 @@ static snd_ctl_numid_t *remap_find_numid_app(snd_ctl_remap_t *priv, unsigned int snd_ctl_numid_t *numid; size_t count; + if (numid_app == 0) + return NULL; if (!priv->numid_remap_active) return remap_numid_temp(priv, numid_app); numid = priv->numid; @@ -151,6 +159,8 @@ static snd_ctl_numid_t *remap_numid_new(snd_ctl_remap_t *priv, unsigned int numi { snd_ctl_numid_t *numid; + if (numid_app == 0) + return NULL; if (priv->numid_alloc == priv->numid_items) { numid = realloc(priv->numid, (priv->numid_alloc + 16) * sizeof(*numid)); if (numid == NULL) @@ -187,6 +197,8 @@ static snd_ctl_numid_t *remap_find_numid_child(snd_ctl_remap_t *priv, unsigned i snd_ctl_numid_t *numid; size_t count; + if (numid_child == 0) + return NULL; if (!priv->numid_remap_active) return remap_numid_temp(priv, numid_child); numid = priv->numid; @@ -282,8 +294,11 @@ static int remap_id_to_child(snd_ctl_remap_t *priv, snd_ctl_elem_id_t *id, snd_c { snd_ctl_remap_id_t *rid; snd_ctl_numid_t *numid; + bool reloaded = false; + int err; debug_id(id, "%s enter\n", __func__); +_retry: rid = remap_find_id_app(priv, id); if (rid) { if (rid->id_app.numid == 0) { @@ -295,13 +310,21 @@ static int remap_id_to_child(snd_ctl_remap_t *priv, snd_ctl_elem_id_t *id, snd_c } *id = rid->id_child; } else { - if (remap_find_id_child(priv, id)) - return -ENOENT; numid = remap_find_numid_app(priv, id->numid); - if (numid) + if (numid) { id->numid = numid->numid_child; - else - id->numid = 0; + } else { + if (reloaded) + return -ENOENT; + if (priv->list_complete) + return -ENOENT; + /* build whole numid mapping */ + err = remap_load_list(priv); + if (err < 0) + return err; + reloaded = true; + goto _retry; + } } *_rid = rid; debug_id(id, "%s leave\n", __func__); @@ -329,6 +352,7 @@ static int remap_id_to_app(snd_ctl_remap_t *priv, snd_ctl_elem_id_t *id, snd_ctl id->numid = numid->numid_app; } } + debug_id(id, "%s rid %p\n", __func__, rid); return err; } @@ -466,9 +490,8 @@ static int snd_ctl_remap_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info) return snd_ctl_card_info(priv->child, info); } -static int snd_ctl_remap_elem_list(snd_ctl_t *ctl, snd_ctl_elem_list_t *list) +static int _snd_ctl_remap_elem_list(snd_ctl_remap_t *priv, snd_ctl_elem_list_t *list) { - snd_ctl_remap_t *priv = ctl->private_data; snd_ctl_elem_id_t *id; snd_ctl_remap_id_t *rid; snd_ctl_numid_t *numid; @@ -483,13 +506,17 @@ static int snd_ctl_remap_elem_list(snd_ctl_t *ctl, snd_ctl_elem_list_t *list) id = &list->pids[index]; rid = remap_find_id_child(priv, id); if (rid) { - rid->id_app.numid = id->numid; - *id = rid->id_app; + assert(id->numid > 0); + rid->id_child.numid = id->numid; } numid = remap_find_numid_child(priv, id->numid); if (numid == NULL) return -EIO; id->numid = numid->numid_app; + if (rid) { + rid->id_app.numid = id->numid; + *id = rid->id_app; + } } if (list->offset >= list->count + priv->map_items + priv->sync_switch_items) return 0; @@ -510,9 +537,40 @@ static int snd_ctl_remap_elem_list(snd_ctl_t *ctl, snd_ctl_elem_list_t *list) } } list->count += priv->map_items + priv->sync_switch_items; + if (list->offset < priv->list_first) + priv->list_first = list->offset; + if (list->offset == priv->list_last && list->offset + list->used > priv->list_last) + priv->list_last = list->offset + list->used; + priv->list_complete = priv->list_first == 0 && list->count == priv->list_last; return 0; } +static int snd_ctl_remap_elem_list(snd_ctl_t *ctl, snd_ctl_elem_list_t *list) +{ + snd_ctl_remap_t *priv = ctl->private_data; + + return _snd_ctl_remap_elem_list(priv, list); +} + +static int remap_load_list(snd_ctl_remap_t *remap) +{ + snd_ctl_elem_list_t list; + int err = 0; + + memset(&list, 0, sizeof(list)); + do { + err = _snd_ctl_remap_elem_list(remap, &list); + if (err < 0) + break; + err = snd_ctl_elem_list_alloc_space(&list, list.count); + if (err < 0) + break; + } while (list.count != list.used); + if (err < 0) + free(list.pids); + return err; +} + #ifndef DOC_HIDDEN #define ACCESS_BITS(bits) \ (bits & (SNDRV_CTL_ELEM_ACCESS_READWRITE|\ @@ -1674,6 +1732,7 @@ int snd_ctl_remap_open(snd_ctl_t **handlep, const char *name, snd_config_t *rema priv->numid_remap_active = priv->map_items > 0 || priv->sync_items; + priv->list_first = UINT_MAX; priv->child = child; err = snd_ctl_new(&ctl, SND_CTL_TYPE_REMAP, name, mode); if (err < 0) { From ebf2efae0a7a27296ccfd6a94e0fa1a39af7a6e4 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 4 Feb 2026 18:42:56 +0100 Subject: [PATCH 13/14] control: remap - cosmetic code reorganization Signed-off-by: Jaroslav Kysela --- src/control/control_remap.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/control/control_remap.c b/src/control/control_remap.c index f7f118aa..4d666bb4 100644 --- a/src/control/control_remap.c +++ b/src/control/control_remap.c @@ -314,9 +314,7 @@ _retry: if (numid) { id->numid = numid->numid_child; } else { - if (reloaded) - return -ENOENT; - if (priv->list_complete) + if (reloaded || priv->list_complete) return -ENOENT; /* build whole numid mapping */ err = remap_load_list(priv); From 541427761292ac75f2bca2200aacf5aab329729e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 4 Feb 2026 18:43:57 +0100 Subject: [PATCH 14/14] ucm: fix invalid pointer dereference in parse_open_variables() When the string with variables is not parseable, do not try to free invalid cfg pointer. Signed-off-by: Jaroslav Kysela --- src/ucm/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ucm/main.c b/src/ucm/main.c index 21a39a34..26b0ea20 100644 --- a/src/ucm/main.c +++ b/src/ucm/main.c @@ -1702,7 +1702,7 @@ const char *parse_open_variables(snd_use_case_mgr_t *uc_mgr, const char *name) { const char *end, *id; char *args, *var; - snd_config_t *cfg, *n; + snd_config_t *cfg = NULL, *n; snd_config_iterator_t i, next; char vname[128]; size_t l; @@ -1739,7 +1739,8 @@ const char *parse_open_variables(snd_use_case_mgr_t *uc_mgr, const char *name) } skip: - snd_config_delete(cfg); + if (cfg) + snd_config_delete(cfg); return end + 3; }