From 3539374ba70031cd1e1b6f100f617b5fe08b226b Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Sat, 14 Jun 2025 13:54:23 +0300 Subject: [PATCH] spa: alsa: fix some coverity warnings NULL checks. Change pa_x* malloc functions act like the pulseaudio ones: assert on failure, as code assumes that. --- spa/plugins/alsa/acp/acp.c | 20 +++++++++++++++----- spa/plugins/alsa/acp/alsa-ucm.c | 2 +- spa/plugins/alsa/acp/compat.h | 21 +++++++++++++-------- spa/plugins/alsa/alsa-pcm.c | 2 +- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/spa/plugins/alsa/acp/acp.c b/spa/plugins/alsa/acp/acp.c index 07e9080d9..5b3de930b 100644 --- a/spa/plugins/alsa/acp/acp.c +++ b/spa/plugins/alsa/acp/acp.c @@ -8,6 +8,7 @@ #include #include +#include #include int _acp_log_level = 1; @@ -372,7 +373,7 @@ static int add_pro_profile(pa_card *impl, uint32_t index) dev = -1; while (1) { - char desc[128], devstr[128], *name; + char desc[128], devstr[128]; if ((err = snd_ctl_pcm_next_device(ctl_hndl, &dev)) < 0) { pa_log_error("error iterating devices: %s", snd_strerror(err)); @@ -396,8 +397,13 @@ static int add_pro_profile(pa_card *impl, uint32_t index) pa_log_error("error pcm info: %s", snd_strerror(err)); } if (err >= 0) { + spa_autofree char *name = NULL; pa_assert_se(asprintf(&name, "Mapping pro-output-%d", dev) >= 0); m = pa_alsa_mapping_get(ps, name); + } else { + m = NULL; + } + if (m) { m->description = pa_xstrdup(desc); m->device_strings = pa_split_spaces_strv(devstr); @@ -419,7 +425,6 @@ static int add_pro_profile(pa_card *impl, uint32_t index) n_playback++; } pa_idxset_put(ap->output_mappings, m, NULL); - free(name); } snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE); @@ -428,8 +433,13 @@ static int add_pro_profile(pa_card *impl, uint32_t index) pa_log_error("error pcm info: %s", snd_strerror(err)); } if (err >= 0) { + spa_autofree char *name = NULL; pa_assert_se(asprintf(&name, "Mapping pro-input-%d", dev) >= 0); m = pa_alsa_mapping_get(ps, name); + } else { + m = NULL; + } + if (m) { m->description = pa_xstrdup(desc); m->device_strings = pa_split_spaces_strv(devstr); @@ -451,7 +461,6 @@ static int add_pro_profile(pa_card *impl, uint32_t index) n_capture++; } pa_idxset_put(ap->input_mappings, m, NULL); - free(name); } } snd_ctl_close(ctl_hndl); @@ -1190,7 +1199,7 @@ uint32_t acp_card_find_best_profile_index(struct acp_card *card, const char *nam static void find_mixer(pa_card *impl, pa_alsa_device *dev, const char *element, bool ignore_dB) { - const char *mdev; + const char *mdev = NULL; pa_alsa_mapping *mapping = dev->mapping; if (!mapping && !element) @@ -1199,7 +1208,8 @@ static void find_mixer(pa_card *impl, pa_alsa_device *dev, const char *element, if (!element && mapping && pa_alsa_path_set_is_empty(dev->mixer_path_set)) return; - mdev = pa_proplist_gets(mapping->proplist, "alsa.mixer_device"); + if (mapping) + mdev = pa_proplist_gets(mapping->proplist, "alsa.mixer_device"); if (mdev) { dev->mixer_handle = pa_alsa_open_mixer_by_name(impl->ucm.mixers, mdev, true); } else { diff --git a/spa/plugins/alsa/acp/alsa-ucm.c b/spa/plugins/alsa/acp/alsa-ucm.c index 73466f004..d67ac91b5 100644 --- a/spa/plugins/alsa/acp/alsa-ucm.c +++ b/spa/plugins/alsa/acp/alsa-ucm.c @@ -1741,7 +1741,7 @@ int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, pa_card *card, pa_alsa_prof ret = -1; } - } else if (ucm->active_verb) { + } else if (ucm->active_verb && old_profile) { /* Disable modifiers not in new profile. Has to be done before * devices, because _dismod fails if a modifier's supported * devices are disabled. */ diff --git a/spa/plugins/alsa/acp/compat.h b/spa/plugins/alsa/acp/compat.h index c7779759f..f7592e1a6 100644 --- a/spa/plugins/alsa/acp/compat.h +++ b/spa/plugins/alsa/acp/compat.h @@ -327,18 +327,23 @@ static inline size_t pa_snprintf(char *str, size_t size, const char *format, ... return ret; } -#define pa_xstrdup(s) ((s) != NULL ? strdup(s) : NULL) -#define pa_xstrndup(s,n) ((s) != NULL ? strndup(s,n) : NULL) +#define pa_xnullcheck(p) ({ void *_mem_alloc = (p); spa_assert_se(_mem_alloc); _mem_alloc; }) +#define pa_xstrdup(s) ((s) != NULL ? pa_xnullcheck(strdup(s)) : NULL) +#define pa_xstrndup(s,n) ((s) != NULL ? pa_xnullcheck(strndup(s,n)) : NULL) #define pa_xfree free -#define pa_xmalloc malloc -#define pa_xnew0(t,n) calloc(n, sizeof(t)) +#define pa_xmalloc(n) pa_xnullcheck(malloc(n)) +#define pa_xnew0(t,n) pa_xnullcheck(calloc((n), sizeof(t))) #define pa_xnew(t,n) pa_xnew0(t,n) -#define pa_xrealloc realloc -#define pa_xrenew(t,p,n) ((t*) realloc(p, (n)*sizeof(t))) +#define pa_xrenew(t,p,n) ((t*) pa_xnullcheck(realloc(p, (n)*sizeof(t)))) static inline void* pa_xmemdup(const void *p, size_t l) { - return memcpy(malloc(l), p, l); - + if (!p) { + return NULL; + } else { + void *dst = pa_xmalloc(l); + memcpy(dst, p, l); + return dst; + } } #define pa_xnewdup(t,p,n) ((t*) pa_xmemdup((p), (n)*sizeof(t))) diff --git a/spa/plugins/alsa/alsa-pcm.c b/spa/plugins/alsa/alsa-pcm.c index 73df819ba..6d6e8133c 100644 --- a/spa/plugins/alsa/alsa-pcm.c +++ b/spa/plugins/alsa/alsa-pcm.c @@ -968,7 +968,7 @@ int spa_alsa_init(struct state *state, const struct spa_dict *info) snd_config_update_free_global(); - if ((str = spa_dict_lookup(info, "device.profile.pro")) != NULL) + if (info && (str = spa_dict_lookup(info, "device.profile.pro")) != NULL) state->is_pro = spa_atob(str); state->multi_rate = true;