From: Jaroslav Kysela Date: Mon, 10 Nov 2025 16:56:27 +0000 (+0100) Subject: coverity.com fixes - initial round X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=47f4f9b73bb51e3b26d9da44ad31fea546382aeb;p=alsa-lib.git coverity.com fixes - initial round This commit tries to fix a bunch of issues found by coverity.com. Signed-off-by: Jaroslav Kysela --- diff --git a/aserver/aserver.c b/aserver/aserver.c index 823b345c..1ef6ef56 100644 --- a/aserver/aserver.c +++ b/aserver/aserver.c @@ -221,7 +221,7 @@ LIST_HEAD(inet_pendings); static int pcm_handler(waiter_t *waiter, unsigned short events) { client_t *client = waiter->private_data; - char buf[1]; + char buf[1] = {0}; ssize_t n; if (events & POLLIN) { n = write(client->poll_fd, buf, 1); @@ -321,17 +321,19 @@ static int pcm_shm_open(client_t *client, int *cookie) static int pcm_shm_close(client_t *client) { + snd_pcm_shm_ctrl_t *ctrl; int err; - snd_pcm_shm_ctrl_t *ctrl = client->transport.shm.ctrl; + if (client->polling) { del_waiter(client->device.pcm.fd); client->polling = 0; } err = snd_pcm_close(client->device.pcm.handle); - ctrl->result = err; if (err < 0) ERROR("snd_pcm_close"); - if (client->transport.shm.ctrl) { + ctrl = client->transport.shm.ctrl; + if (ctrl) { + ctrl->result = err; err = shmdt((void *)client->transport.shm.ctrl); if (err < 0) SYSERROR("shmdt failed"); @@ -348,7 +350,7 @@ static int shm_ack(client_t *client) { struct pollfd pfd; int err; - char buf[1]; + char buf[1] = {0}; pfd.fd = client->ctrl_fd; pfd.events = POLLHUP; if (poll(&pfd, 1, 0) == 1) @@ -531,7 +533,7 @@ transport_ops_t pcm_shm_ops = { static int ctl_handler(waiter_t *waiter, unsigned short events) { client_t *client = waiter->private_data; - char buf[1] = ""; + char buf[1] = {0}; ssize_t n; if (events & POLLIN) { n = write(client->poll_fd, buf, 1); @@ -585,16 +587,17 @@ static int ctl_shm_open(client_t *client, int *cookie) static int ctl_shm_close(client_t *client) { int err; - snd_ctl_shm_ctrl_t *ctrl = client->transport.shm.ctrl; + snd_ctl_shm_ctrl_t *ctrl; if (client->polling) { del_waiter(client->device.ctl.fd); client->polling = 0; } err = snd_ctl_close(client->device.ctl.handle); - ctrl->result = err; if (err < 0) ERROR("snd_ctl_close"); - if (client->transport.shm.ctrl) { + ctrl = client->transport.shm.ctrl; + if (ctrl) { + ctrl->result = err; err = shmdt((void *)client->transport.shm.ctrl); if (err < 0) SYSERROR("shmdt failed"); @@ -738,6 +741,10 @@ static int snd_client_open(client_t *client) ans.result = -EINVAL; goto _answer; } + if (sizeof(client->name) < (size_t)(req.namelen + 1)) { + ans.result = -EINVAL; + goto _answer; + } name = alloca(req.namelen + 1); err = read(client->ctrl_fd, name, req.namelen); if (err < 0) { @@ -779,7 +786,7 @@ static int snd_client_open(client_t *client) ans.result = -ENOMEM; goto _answer; } - strcpy(client->name, name); + snd_strlcpy(client->name, name, sizeof(client->name)); client->stream = req.stream; client->mode = req.mode; diff --git a/src/async.c b/src/async.c index f85980fa..989738ec 100644 --- a/src/async.c +++ b/src/async.c @@ -150,7 +150,6 @@ int snd_async_add_handler(snd_async_handler_t **handler, int fd, int snd_async_del_handler(snd_async_handler_t *handler) { int err = 0, err2 = 0; - int was_empty; assert(handler); if (handler->type != SND_ASYNC_HANDLER_GENERIC) { struct list_head *alist; @@ -184,15 +183,16 @@ int snd_async_del_handler(snd_async_handler_t *handler) } } _glist: - was_empty = list_empty(&snd_async_handlers); - list_del(&handler->glist); - if (!was_empty && list_empty(&snd_async_handlers)) { - err = sigaction(snd_async_signo, &previous_action, NULL); - if (err < 0) { - snd_errornum(CORE, "sigaction"); - return -errno; + if (!list_empty(&snd_async_handlers)) { + list_del(&handler->glist); + if (list_empty(&snd_async_handlers)) { + err = sigaction(snd_async_signo, &previous_action, NULL); + if (err < 0) { + snd_errornum(CORE, "sigaction"); + return -errno; + } + memset(&previous_action, 0, sizeof(previous_action)); } - memset(&previous_action, 0, sizeof(previous_action)); } free(handler); return err ? err : err2; diff --git a/src/conf.c b/src/conf.c index 0f3dc6d6..49499ecd 100644 --- a/src/conf.c +++ b/src/conf.c @@ -1299,13 +1299,18 @@ static int parse_array_def(snd_config_t *parent, input_t *input, int *idx, int s { char endchr; if (!skip) { +#if 0 /* n is always NULL for this moment */ if (n) { if (n->type != SND_CONFIG_TYPE_COMPOUND) { snd_error(CORE, "%s is not a compound", id); err = -EINVAL; goto __end; } - } else { + } else +#else + assert(n == NULL); +#endif + { err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent); if (err < 0) goto __end; @@ -1318,6 +1323,8 @@ static int parse_array_def(snd_config_t *parent, input_t *input, int *idx, int s err = parse_array_defs(n, input, skip, override); endchr = ']'; } + if (err < 0) + goto __end; c = get_nonwhite(input); if (c < 0) { err = c; @@ -3493,7 +3500,7 @@ int snd_config_save(snd_config_t *config, snd_output_t *out) #define SND_CONFIG_SEARCHV(config, result, fcn) \ { \ - snd_config_t *n; \ + snd_config_t *n = NULL; \ va_list arg; \ assert(config); \ va_start(arg, result); \ @@ -3517,7 +3524,7 @@ int snd_config_save(snd_config_t *config, snd_output_t *out) #define SND_CONFIG_SEARCHVA(root, config, result, fcn) \ { \ - snd_config_t *n; \ + snd_config_t *n = NULL; \ va_list arg; \ assert(config); \ va_start(arg, result); \ @@ -4565,7 +4572,10 @@ int snd_config_update_r(snd_config_t **_top, snd_config_update_t **_update, cons } for (k = 0; k < local->count; ++k) { struct stat64 st; - struct finfo *lf = &local->finfo[k]; + struct finfo *lf; + +_nextf: + lf = &local->finfo[k]; if (stat64(lf->name, &st) >= 0) { lf->dev = st.st_dev; lf->ino = st.st_ino; @@ -4573,9 +4583,13 @@ int snd_config_update_r(snd_config_t **_top, snd_config_update_t **_update, cons } else { snd_error(CORE, "Cannot access file %s", lf->name); free(lf->name); - memmove(&local->finfo[k], &local->finfo[k+1], sizeof(struct finfo) * (local->count - k - 1)); - k--; local->count--; + if (k < local->count) { + memmove(&local->finfo[k], &local->finfo[k+1], sizeof(struct finfo) * (local->count - k)); + goto _nextf; + } else { + break; + } } } if (!update) diff --git a/src/control/control_remap.c b/src/control/control_remap.c index 2ed97d23..7d90d7ad 100644 --- a/src/control/control_remap.c +++ b/src/control/control_remap.c @@ -770,7 +770,7 @@ static int remap_map_elem_write(snd_ctl_remap_t *priv, snd_ctl_elem_value_t *con } for (src_index = 1; src_index < mctl->src_channels; src_index++) { dst = mctl->channel_map[base_idx + src_index]; - if ((unsigned long)dst < ARRAY_SIZE(control->value.integer.value)) { + if ((unsigned long)dst < ARRAY_SIZE(control->value.integer64.value)) { changes |= control2.value.integer64.value[dst] != control->value.integer64.value[index]; control2.value.integer64.value[dst] = control->value.integer64.value[index]; } diff --git a/src/control/control_shm.c b/src/control/control_shm.c index abf8174a..44f0a7bc 100644 --- a/src/control/control_shm.c +++ b/src/control/control_shm.c @@ -70,7 +70,7 @@ static int snd_ctl_shm_action_fd(snd_ctl_t *ctl, int *fd) { snd_ctl_shm_t *shm = ctl->private_data; int err; - char buf[1]; + char buf[1] = {0}; volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; err = write(shm->socket, buf, 1); if (err != 1) @@ -483,6 +483,11 @@ int snd_ctl_shm_open(snd_ctl_t **handlep, const char *name, const char *sockname result = -EINVAL; goto _err; } + if (ans.result < INT_MIN || ans.result > INT_MAX) { + snd_error(CONTROL, "invalid data error"); + result = -EINVAL; + goto _err; + } result = ans.result; if (result < 0) goto _err; @@ -519,7 +524,8 @@ int snd_ctl_shm_open(snd_ctl_t **handlep, const char *name, const char *sockname return 0; _err: - close(sock); + if (sock >= 0) + close(sock); if (ctrl) shmdt(ctrl); free(shm); diff --git a/src/control/namehint.c b/src/control/namehint.c index 4b2f98b6..6ce033cc 100644 --- a/src/control/namehint.c +++ b/src/control/namehint.c @@ -587,7 +587,7 @@ int snd_device_name_hint(int card, const char *iface, void ***hints) struct hint_list list; char ehints[24]; const char *str; - snd_config_t *conf, *local_config = NULL, *local_config_rw = NULL; + snd_config_t *conf, *local_config = NULL, *local_config_rw; snd_config_update_t *local_config_update = NULL; snd_config_iterator_t i, next; int err; @@ -628,6 +628,8 @@ int snd_device_name_hint(int card, const char *iface, void ***hints) err = get_card_name(&list, card); if (err >= 0) err = add_card(local_config, local_config_rw, &list, card); + if (err < 0) + goto __error; } else { add_software_devices(local_config, local_config_rw, &list); err = snd_card_next(&card); @@ -669,10 +671,8 @@ int snd_device_name_hint(int card, const char *iface, void ***hints) else *hints = (void **)list.list; free(list.cardname); - if (local_config_rw) - snd_config_delete(local_config_rw); - if (local_config) - snd_config_delete(local_config); + snd_config_delete(local_config_rw); + snd_config_delete(local_config); if (local_config_update) snd_config_update_free(local_config_update); return err; diff --git a/src/control/setup.c b/src/control/setup.c index 7ae7b3e9..669e5fcb 100644 --- a/src/control/setup.c +++ b/src/control/setup.c @@ -221,10 +221,12 @@ static int snd_config_get_ctl_elem_enumerated(snd_config_t *n, snd_ctl_t *ctl, unsigned int idx, items; switch (snd_config_get_type(n)) { case SND_CONFIG_TYPE_INTEGER: - snd_config_get_integer(n, &val); + if (snd_config_get_integer(n, &val) < 0) + return -1; return val; case SND_CONFIG_TYPE_STRING: - snd_config_get_string(n, &str); + if (snd_config_get_string(n, &str) < 0) + return -1; break; default: return -1; @@ -586,8 +588,7 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_da if (err != -ENOMEM && optional) err = 0; /* ignore the error */ } - if (conf) - snd_config_delete(conf); + snd_config_delete(conf); return err; } diff --git a/src/error.c b/src/error.c index e6ed6abb..e575f2eb 100644 --- a/src/error.c +++ b/src/error.c @@ -368,8 +368,8 @@ void snd_lib_log(int prio, int interface, const char *file, int line, const char void snd_lib_check(int interface, const char *file, int line, const char *function, int errcode, const char *fmt, ...) { const char *verbose; - va_list arg; + va_start(arg, fmt); verbose = getenv("LIBASOUND_DEBUG"); if (! verbose || ! *verbose) diff --git a/src/mixer/simple_abst.c b/src/mixer/simple_abst.c index b60c0eef..4dd21e90 100644 --- a/src/mixer/simple_abst.c +++ b/src/mixer/simple_abst.c @@ -352,8 +352,7 @@ int snd_mixer_simple_basic_register(snd_mixer_t *mixer, snd_mixer_class_free(class); return err; } - if (top) - snd_config_delete(top); + snd_config_delete(top); if (classp) *classp = class; return 0; diff --git a/src/mixer/simple_none.c b/src/mixer/simple_none.c index 4c47b168..e0945602 100644 --- a/src/mixer/simple_none.c +++ b/src/mixer/simple_none.c @@ -652,7 +652,7 @@ static int selem_write(snd_mixer_elem_t *elem) err = selem_write_main(elem); if (err < 0) - selem_read(elem); + (void)selem_read(elem); return err; } @@ -984,6 +984,8 @@ static int _snd_mixer_selem_set_volume(snd_mixer_elem_t *elem, int dir, snd_mixe static int _snd_mixer_selem_set_switch(snd_mixer_elem_t *elem, int dir, snd_mixer_selem_channel_id_t channel, int value) { selem_none_t *s = snd_mixer_elem_get_private(elem); + if (channel < 0 || channel > 31) + return 0; if ((unsigned int) channel >= s->str[dir].channels) return 0; if (s->selem.caps & @@ -1247,6 +1249,8 @@ static int get_switch_ops(snd_mixer_elem_t *elem, int dir, dir = SM_PLAY; if ((unsigned int) channel >= s->str[dir].channels) return -EINVAL; + if (channel < 0 || channel > 31) + return -EINVAL; *value = !!(s->str[dir].sw & (1 << channel)); return 0; } diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index a6f500cb..11b15100 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -2580,8 +2580,8 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name, char *val; if (snd_config_get_id(pcm_conf, &id) < 0) id = NULL; - val = NULL; - snd_config_get_ascii(pcm_conf, &val); + if (snd_config_get_ascii(pcm_conf, &val) < 0) + val = NULL; snd_error(PCM, "Invalid type for PCM %s%sdefinition (id: %s, value: %s)", name ? name : "", name ? " " : "", id, val); free(val); return -EINVAL; @@ -3126,7 +3126,7 @@ int snd_pcm_avail_delay(snd_pcm_t *pcm, while (1) { sf = __snd_pcm_avail_update(pcm); if (sf < 0) { - err = (int)sf; + err = sf < INT_MIN ? -EOVERFLOW : (int)sf; goto unlock; } if (ok && sf == *availp) @@ -3335,6 +3335,8 @@ int snd_pcm_area_copy(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes_t return 0; dst = snd_pcm_channel_area_addr(dst_area, dst_offset); width = snd_pcm_format_physical_width(format); + if (width < 0) + return width; if (src_area->step == (unsigned int) width && dst_area->step == (unsigned int) width) { size_t bytes = samples * width / 8; @@ -7682,8 +7684,7 @@ snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_ frames = size; if (frames > (snd_pcm_uframes_t) avail) frames = avail; - if (! frames) - break; + /* frames must be at least 1 here (see while condition) */ err = func(pcm, areas, offset, frames); if (err < 0) break; @@ -8059,7 +8060,7 @@ void snd_pcm_unlink_appl_ptr(snd_pcm_t *pcm, snd_pcm_t *slave) * */ -#ifndef DOC_HIDDEN +#if !defined(DOC_HIDDEN) && !defined(__COVERITY__) #ifdef USE_VERSIONED_SYMBOLS @@ -8295,7 +8296,7 @@ OBSOLETE1(snd_pcm_sw_params_get_stop_threshold, ALSA_0.9, ALSA_0.9.0rc4); OBSOLETE1(snd_pcm_sw_params_get_silence_threshold, ALSA_0.9, ALSA_0.9.0rc4); OBSOLETE1(snd_pcm_sw_params_get_silence_size, ALSA_0.9, ALSA_0.9.0rc4); -#endif /* DOC_HIDDEN */ +#endif /* DOC_HIDDEN/COVERITY */ static int chmap_equal(const snd_pcm_chmap_t *a, const snd_pcm_chmap_t *b) { @@ -8794,7 +8795,7 @@ int snd_pcm_recover(snd_pcm_t *pcm, int err, int silent) if (err == -ESTRPIPE) { while ((err = snd_pcm_resume(pcm)) == -EAGAIN) /* wait until suspend flag is released */ - poll(NULL, 0, 1000); + (void)poll(NULL, 0, 1000); if (err < 0) { err = snd_pcm_prepare(pcm); if (err < 0) { diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c index 304c1883..a08bbe6d 100644 --- a/src/pcm/pcm_direct.c +++ b/src/pcm/pcm_direct.c @@ -1763,7 +1763,11 @@ int snd_pcm_direct_parse_bindings(snd_pcm_direct_t *dmix, long cchannel, schannel; if (snd_config_get_id(n, &id) < 0) continue; - safe_strtol(id, &cchannel); + err = safe_strtol(id, &cchannel); + if (err < 0) { + free(bindings); + return -EINVAL; + } if (snd_config_get_integer(n, &schannel) < 0) { snd_error(PCM, "unable to get slave channel (should be integer type) in binding: %s", id); free(bindings); @@ -1907,6 +1911,14 @@ static int _snd_pcm_direct_get_slave_ipc_offset(snd_config_t *root, device = 0; if (subdevice < 0) subdevice = 0; + if (card < 0 || card >= (1 << (31 - 12 - 1))) + return -EOVERFLOW; + if (device >= (1 << 6)) + return -EOVERFLOW; + if (subdevice >= (1 << 4)) + return -EOVERFLOW; + if (direction < 0 || direction > 1) + return -EOVERFLOW; return (direction << 1) + (device << 2) + (subdevice << 8) + (card << 12); } diff --git a/src/pcm/pcm_dmix_x86_64.c b/src/pcm/pcm_dmix_x86_64.c index 84eb68f1..92619a7d 100644 --- a/src/pcm/pcm_dmix_x86_64.c +++ b/src/pcm/pcm_dmix_x86_64.c @@ -69,13 +69,19 @@ static void mix_select_callbacks(snd_pcm_direct_t *dmix) { static int smp = 0; + unsigned int format = dmix->shmptr->s.format; if (!dmix->direct_memory_access) { generic_mix_select_callbacks(dmix); return; } - if (!((1ULL<< dmix->shmptr->s.format) & x86_64_dmix_supported_format)) { + if (format > 31) { + generic_mix_select_callbacks(dmix); + return; + } + + if (!((1U << format) & x86_64_dmix_supported_format)) { generic_mix_select_callbacks(dmix); return; } diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c index 65da72a9..4ef158c0 100644 --- a/src/pcm/pcm_dshare.c +++ b/src/pcm/pcm_dshare.c @@ -87,7 +87,12 @@ static void share_areas(snd_pcm_direct_t *dshare, channels = dshare->channels; format = dshare->shmptr->s.format; if (dshare->interleaved) { - unsigned int fbytes = snd_pcm_format_physical_width(format) / 8; + int width = snd_pcm_format_physical_width(format); + unsigned int fbytes; + + if (width < 0) + return; + fbytes = width / 8; memcpy(((char *)dst_areas[0].addr) + (dst_ofs * channels * fbytes), ((char *)src_areas[0].addr) + (src_ofs * channels * fbytes), size * channels * fbytes); diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c index 8c3b53ae..6a803b2c 100644 --- a/src/pcm/pcm_dsnoop.c +++ b/src/pcm/pcm_dsnoop.c @@ -81,11 +81,16 @@ static void snoop_areas(snd_pcm_direct_t *dsnoop, { unsigned int chn, schn, channels; snd_pcm_format_t format; + unsigned int fbytes; + int pwidth; channels = dsnoop->channels; format = dsnoop->shmptr->s.format; if (dsnoop->interleaved) { - unsigned int fbytes = snd_pcm_format_physical_width(format) / 8; + pwidth = snd_pcm_format_physical_width(format); + if (pwidth < 0) + return; + fbytes = pwidth / 8; memcpy(((char *)dst_areas[0].addr) + (dst_ofs * channels * fbytes), ((char *)src_areas[0].addr) + (src_ofs * channels * fbytes), size * channels * fbytes); diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c index f2c73163..ad8cb0db 100644 --- a/src/pcm/pcm_file.c +++ b/src/pcm/pcm_file.c @@ -467,7 +467,12 @@ static int snd_pcm_file_add_frames(snd_pcm_t *pcm, int err = 0; snd_pcm_uframes_t n = frames; snd_pcm_uframes_t cont = file->wbuf_size - file->appl_ptr; - snd_pcm_uframes_t avail = file->wbuf_size - snd_pcm_bytes_to_frames(pcm, file->wbuf_used_bytes); + snd_pcm_sframes_t used = snd_pcm_bytes_to_frames(pcm, file->wbuf_used_bytes); + snd_pcm_uframes_t avail; + + if (used < 0) + return used; + avail = file->wbuf_size - used; if (n > cont) n = cont; if (n > avail) @@ -475,12 +480,15 @@ static int snd_pcm_file_add_frames(snd_pcm_t *pcm, snd_pcm_areas_copy(file->wbuf_areas, file->appl_ptr, areas, offset, pcm->channels, n, pcm->format); + used = snd_pcm_frames_to_bytes(pcm, n); + if (used < 0) + return used; frames -= n; offset += n; file->appl_ptr += n; if (file->appl_ptr == file->wbuf_size) file->appl_ptr = 0; - file->wbuf_used_bytes += snd_pcm_frames_to_bytes(pcm, n); + file->wbuf_used_bytes += used; if (file->wbuf_used_bytes > file->buffer_bytes) { err = snd_pcm_file_write_bytes(pcm, file->wbuf_used_bytes - file->buffer_bytes); if (err < 0) @@ -562,16 +570,23 @@ static snd_pcm_sframes_t snd_pcm_file_rewindable(snd_pcm_t *pcm) static snd_pcm_sframes_t snd_pcm_file_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { snd_pcm_file_t *file = pcm->private_data; - snd_pcm_sframes_t err; - snd_pcm_uframes_t n; + snd_pcm_sframes_t err, n; n = snd_pcm_frames_to_bytes(pcm, frames); - if (n > file->wbuf_used_bytes) - frames = snd_pcm_bytes_to_frames(pcm, file->wbuf_used_bytes); + if (n < 0) + return n; + if ((size_t)n > file->wbuf_used_bytes) { + err = snd_pcm_bytes_to_frames(pcm, file->wbuf_used_bytes); + if (err < 0) + return err; + frames = err; + } err = snd_pcm_rewind(file->gen.slave, frames); if (err > 0) { - file->appl_ptr = (file->appl_ptr - err + file->wbuf_size) % file->wbuf_size; n = snd_pcm_frames_to_bytes(pcm, err); + if (n < 0) + return n; + file->appl_ptr = (file->appl_ptr - err + file->wbuf_size) % file->wbuf_size; file->wbuf_used_bytes -= n; } return err; @@ -582,6 +597,8 @@ static snd_pcm_sframes_t snd_pcm_file_forwardable(snd_pcm_t *pcm) snd_pcm_file_t *file = pcm->private_data; snd_pcm_sframes_t res = snd_pcm_forwardable(file->gen.slave); snd_pcm_sframes_t n = snd_pcm_bytes_to_frames(pcm, file->wbuf_size_bytes - file->wbuf_used_bytes); + if (n < 0) + return n; if (res > n) res = n; return res; @@ -590,16 +607,23 @@ static snd_pcm_sframes_t snd_pcm_file_forwardable(snd_pcm_t *pcm) static snd_pcm_sframes_t snd_pcm_file_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames) { snd_pcm_file_t *file = pcm->private_data; - snd_pcm_sframes_t err; - snd_pcm_uframes_t n; + snd_pcm_sframes_t err, n; n = snd_pcm_frames_to_bytes(pcm, frames); - if (file->wbuf_used_bytes + n > file->wbuf_size_bytes) - frames = snd_pcm_bytes_to_frames(pcm, file->wbuf_size_bytes - file->wbuf_used_bytes); + if (n < 0) + return n; + if (file->wbuf_used_bytes + n > file->wbuf_size_bytes) { + err = snd_pcm_bytes_to_frames(pcm, file->wbuf_size_bytes - file->wbuf_used_bytes); + if (err < 0) + return err; + frames = err; + } err = INTERNAL(snd_pcm_forward)(file->gen.slave, frames); if (err > 0) { - file->appl_ptr = (file->appl_ptr + err) % file->wbuf_size; n = snd_pcm_frames_to_bytes(pcm, err); + if (n < 0) + return err; + file->appl_ptr = (file->appl_ptr + err) % file->wbuf_size; file->wbuf_used_bytes += n; } return err; @@ -755,10 +779,14 @@ static int snd_pcm_file_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) snd_pcm_file_t *file = pcm->private_data; unsigned int channel; snd_pcm_t *slave = file->gen.slave; + snd_pcm_sframes_t bsize; int err = _snd_pcm_hw_params_internal(slave, params); if (err < 0) return err; - file->buffer_bytes = snd_pcm_frames_to_bytes(slave, slave->buffer_size); + bsize = snd_pcm_frames_to_bytes(slave, slave->buffer_size); + if (bsize < 0) + return bsize; + file->buffer_bytes = bsize; file->wbuf_size = slave->buffer_size * 2; file->wbuf_size_bytes = snd_pcm_frames_to_bytes(slave, file->wbuf_size); file->wbuf_used_bytes = 0; @@ -932,14 +960,21 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name, file->perm = perm; if (ifname && (stream == SND_PCM_STREAM_CAPTURE)) { - ifd = open(ifname, O_RDONLY); /* TODO: mind blocking mode */ - if (ifd < 0) { + file->ifname = strdup(ifname); + if (file->ifname) + ifd = open(ifname, O_RDONLY); /* TODO: mind blocking mode */ + else + ifd = -1; + if (ifd < 0 || file->ifname == NULL) { + if (ifd >= 0) + close(ifd); + err = -errno; snd_errornum(PCM, "open %s for reading failed", ifname); + free(file->ifname); free(file->fname); free(file); - return -errno; + return err; } - file->ifname = strdup(ifname); } file->fd = fd; file->ifd = ifd; @@ -949,6 +984,8 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name, err = snd_pcm_new(&pcm, SND_PCM_TYPE_FILE, name, slave->stream, slave->mode); if (err < 0) { + if (file->ifname && file->ifd >= 0) + close(file->ifd); free(file->fname); free(file->ifname); free(file); diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index efd838d3..c9fca93c 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -469,8 +469,8 @@ static int snd_pcm_hw_change_timer(snd_pcm_t *pcm, int enable) */ { int ver = 0; - ioctl(hw->period_timer_pfd.fd, - SNDRV_TIMER_IOCTL_PVERSION, &ver); + if (ioctl(hw->period_timer_pfd.fd, SNDRV_TIMER_IOCTL_PVERSION, &ver)) + snd_warn(PCM, "unable to get protocol version"); /* * In older versions, check via poll before read() is * needed because of the confliction between diff --git a/src/pcm/pcm_ladspa.c b/src/pcm/pcm_ladspa.c index 0397219b..fb0f5bec 100644 --- a/src/pcm/pcm_ladspa.c +++ b/src/pcm/pcm_ladspa.c @@ -891,7 +891,7 @@ snd_pcm_ladspa_write_areas(snd_pcm_t *pcm, chn = instance->output.channels.array[idx]; data = instance->output.data[idx]; if (data == NULL) { - data = (LADSPA_Data *)((char *)slave_areas[chn].addr + (areas[chn].first / 8)); + data = (LADSPA_Data *)((char *)slave_areas[chn].addr + (slave_areas[chn].first / 8)); data += slave_offset; } instance->desc->connect_port(instance->handle, instance->output.ports.array[idx], data); @@ -943,7 +943,7 @@ snd_pcm_ladspa_read_areas(snd_pcm_t *pcm, chn = instance->input.channels.array[idx]; data = instance->input.data[idx]; if (data == NULL) { - data = (LADSPA_Data *)((char *)slave_areas[chn].addr + (areas[chn].first / 8)); + data = (LADSPA_Data *)((char *)slave_areas[chn].addr + (slave_areas[chn].first / 8)); data += slave_offset; } instance->desc->connect_port(instance->handle, instance->input.ports.array[idx], data); @@ -1759,7 +1759,9 @@ int _snd_pcm_ladspa_open(snd_pcm_t **pcmp, const char *name, continue; } if (strcmp(id, "channels") == 0) { - snd_config_get_integer(n, &channels); + err = snd_config_get_integer(n, &channels); + if (err < 0) + return err; if (channels > 1024) channels = 1024; if (channels < 0) diff --git a/src/pcm/pcm_meter.c b/src/pcm/pcm_meter.c index c027194d..8fc5c15d 100644 --- a/src/pcm/pcm_meter.c +++ b/src/pcm/pcm_meter.c @@ -443,7 +443,7 @@ static int snd_pcm_meter_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) snd_pcm_meter_t *meter = pcm->private_data; unsigned int channel; snd_pcm_t *slave = meter->gen.slave; - size_t buf_size_bytes; + ssize_t buf_size_bytes; int err; err = snd_pcm_hw_params_slave(pcm, params, snd_pcm_meter_hw_refine_cchange, @@ -457,6 +457,8 @@ static int snd_pcm_meter_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) while (meter->buf_size < slave->rate) meter->buf_size *= 2; buf_size_bytes = snd_pcm_frames_to_bytes(slave, meter->buf_size); + if (buf_size_bytes < 0) + return buf_size_bytes; assert(!meter->buf); meter->buf = malloc(buf_size_bytes); if (!meter->buf) diff --git a/src/pcm/pcm_misc.c b/src/pcm/pcm_misc.c index 570ecd97..d611f6a6 100644 --- a/src/pcm/pcm_misc.c +++ b/src/pcm/pcm_misc.c @@ -619,12 +619,12 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int break; } case 8: { - uint8_t silence = snd_pcm_format_silence_64(format); + uint8_t silence = snd_pcm_format_silence(format); memset(data, silence, samples); break; } case 16: { - uint16_t silence = snd_pcm_format_silence_64(format); + uint16_t silence = snd_pcm_format_silence_16(format); uint16_t *pdata = (uint16_t *)data; if (! silence) memset(data, 0, samples * 2); @@ -635,7 +635,7 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int break; } case 24: { - uint32_t silence = snd_pcm_format_silence_64(format); + uint32_t silence = snd_pcm_format_silence_32(format); uint8_t *pdata = (uint8_t *)data; if (! silence) memset(data, 0, samples * 3); @@ -655,7 +655,7 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int break; } case 32: { - uint32_t silence = snd_pcm_format_silence_64(format); + uint32_t silence = snd_pcm_format_silence_32(format); uint32_t *pdata = (uint32_t *)data; if (! silence) memset(data, 0, samples * 4); diff --git a/src/pcm/pcm_mulaw.c b/src/pcm/pcm_mulaw.c index c6705b2d..5ee72366 100644 --- a/src/pcm/pcm_mulaw.c +++ b/src/pcm/pcm_mulaw.c @@ -251,6 +251,8 @@ static int snd_pcm_mulaw_hw_refine_cprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t err = _snd_pcm_hw_params_set_format(params, SND_PCM_FORMAT_MU_LAW); } + if (err < 0) + return err; err = _snd_pcm_hw_params_set_subformat(params, SND_PCM_SUBFORMAT_STD); if (err < 0) return err; diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c index 7a601763..121c4c20 100644 --- a/src/pcm/pcm_multi.c +++ b/src/pcm/pcm_multi.c @@ -1439,13 +1439,13 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name, _free: if (err < 0) { for (idx = 0; idx < slaves_count; ++idx) { - if (slaves_pcm[idx]) + if (slaves_pcm && slaves_pcm[idx]) snd_pcm_close(slaves_pcm[idx]); } } if (slaves_conf) { for (idx = 0; idx < slaves_count; ++idx) { - if (slaves_conf[idx]) + if (slaves_conf && slaves_conf[idx]) snd_config_delete(slaves_conf[idx]); } free(slaves_conf); diff --git a/src/pcm/pcm_params.c b/src/pcm/pcm_params.c index 833d0dc9..0536252e 100644 --- a/src/pcm/pcm_params.c +++ b/src/pcm/pcm_params.c @@ -967,6 +967,8 @@ static int snd_pcm_hw_param_set_near_minmax(snd_pcm_t *pcm, if (boundary_lt(min, *mindir, max, *maxdir)) { tmp = *params; err = snd_pcm_hw_param_set_near(pcm, &tmp, var, &max, maxdir); + if (err < 0) + return err; } else { max = min; *maxdir = *mindir; diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c index 5172a7d2..ddda92ca 100644 --- a/src/pcm/pcm_plug.c +++ b/src/pcm/pcm_plug.c @@ -235,6 +235,8 @@ static const char linear_format_widths[32] = { static int check_linear_format(const snd_pcm_format_mask_t *format_mask, int wid, int sgn, int ed) { int e, s; + if (wid < 1 || wid > 32) + return SND_PCM_FORMAT_UNKNOWN; if (! linear_format_widths[wid - 1]) return SND_PCM_FORMAT_UNKNOWN; for (e = 0; e < 2; e++) { @@ -450,13 +452,15 @@ static int snd_pcm_plug_change_channels(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm snd_pcm_route_ttable_entry_t v = SND_PCM_PLUGIN_ROUTE_FULL; if (rpolicy == PLUG_ROUTE_POLICY_AVERAGE) { if (pcm->stream == SND_PCM_STREAM_PLAYBACK && - clt->channels > slv->channels) { + clt->channels > slv->channels && + slv->channels > 0) { int srcs = clt->channels / slv->channels; if (s < clt->channels % slv->channels) srcs++; v /= srcs; } else if (pcm->stream == SND_PCM_STREAM_CAPTURE && - slv->channels > clt->channels) { + slv->channels > clt->channels && + clt->channels > 0) { int srcs = slv->channels / clt->channels; if (s < slv->channels % clt->channels) srcs++; @@ -1338,6 +1342,7 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name, SND_PCM_HW_PARAM_RATE, SCONF_UNCHANGED, &srate); if (err < 0) return err; + csize = ssize = cused = sused = 0; #ifdef BUILD_PCM_PLUGIN_ROUTE if (tt) { err = snd_pcm_route_determine_ttable(tt, &csize, &ssize); @@ -1352,6 +1357,7 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name, } err = snd_pcm_route_load_ttable(tt, ttable, csize, ssize, &cused, &sused, -1); if (err < 0) { + free(ttable); snd_config_delete(sconf); return err; } @@ -1365,8 +1371,10 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name, err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf); snd_config_delete(sconf); - if (err < 0) + if (err < 0) { + free(ttable); return err; + } err = snd_pcm_plug_open(pcmp, name, sformat, schannels, srate, rate_converter, route_policy, ttable, ssize, cused, sused, spcm, 1); if (err < 0) diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c index 3847a82b..d54be3c2 100644 --- a/src/pcm/pcm_rate.c +++ b/src/pcm/pcm_rate.c @@ -88,6 +88,12 @@ rate_alloc_tmp_buf(snd_pcm_format_t format, int width = snd_pcm_format_physical_width(format); unsigned int i; + if (width < 0 || width > 128) + return NULL; + if (channels > 1024) + return NULL; + if (frames > 10*1024*1024) + return NULL; ap = malloc(sizeof(*ap) * channels); if (!ap) return NULL; @@ -320,6 +326,9 @@ static int choose_preferred_format(snd_pcm_rate_t *rate) if (!in_mask || !out_mask) return 0; + if (rate->orig_in_format < 0 || rate->orig_in_format > 63) + return -EINVAL; + if (rate->orig_in_format == rate->orig_out_format) if (in_mask & out_mask & (1ULL << rate->orig_in_format)) return 0; /* nothing changed */ diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c index 29fb51e9..3836dcc3 100644 --- a/src/pcm/pcm_route.c +++ b/src/pcm/pcm_route.c @@ -1339,6 +1339,7 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name, continue; } snd_error(PCM, "Unknown field %s", id); + snd_pcm_free_chmaps(chmaps); return -EINVAL; } if (!slave) { @@ -1368,7 +1369,8 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name, err = determine_chmap(tt, &tt_chmap); if (err < 0) { - free(ttable); + snd_config_delete(sconf); + snd_pcm_free_chmaps(chmaps); return err; } @@ -1376,7 +1378,6 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name, snd_config_delete(sconf); if (err < 0) { free(tt_chmap); - free(ttable); snd_pcm_free_chmaps(chmaps); return err; } diff --git a/src/pcm/pcm_share.c b/src/pcm/pcm_share.c index 7927b646..12205fe1 100644 --- a/src/pcm/pcm_share.c +++ b/src/pcm/pcm_share.c @@ -288,7 +288,7 @@ static snd_pcm_uframes_t _snd_pcm_share_missing(snd_pcm_t *pcm) update_poll: if (ready != share->ready) { - char buf[1]; + char buf[1] = {0}; while (1) { if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { if (ready) @@ -366,14 +366,15 @@ static void *snd_pcm_share_thread(void *data) struct pollfd pfd[2]; int err; + Pthread_mutex_lock(&slave->mutex); pfd[0].fd = slave->poll[0]; pfd[0].events = POLLIN; err = snd_pcm_poll_descriptors(spcm, &pfd[1], 1); if (err != 1) { snd_error(PCM, "invalid poll descriptors %d", err); + Pthread_mutex_unlock(&slave->mutex); return NULL; } - Pthread_mutex_lock(&slave->mutex); err = pipe(slave->poll); if (err < 0) { snd_errornum(PCM, "can't create a pipe"); @@ -412,9 +413,9 @@ static void *snd_pcm_share_thread(void *data) Pthread_mutex_unlock(&slave->mutex); err = poll(pfd, 2, -1); Pthread_mutex_lock(&slave->mutex); - if (pfd[0].revents & POLLIN) { + if (err > 0 && (pfd[0].revents & POLLIN) != 0) { char buf[1]; - read(pfd[0].fd, buf, 1); + (void)read(pfd[0].fd, buf, 1); } } else { slave->polling = 0; @@ -931,9 +932,12 @@ static int snd_pcm_share_start(snd_pcm_t *pcm) snd_pcm_share_slave_t *slave = share->slave; snd_pcm_t *spcm = slave->pcm; int err = 0; - if (share->state != SND_PCM_STATE_PREPARED) - return -EBADFD; + Pthread_mutex_lock(&slave->mutex); + if (share->state != SND_PCM_STATE_PREPARED) { + err = -EBADFD; + goto _end; + } share->state = SND_PCM_STATE_RUNNING; if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { snd_pcm_uframes_t hw_avail = snd_pcm_mmap_playback_hw_avail(pcm); @@ -1152,8 +1156,13 @@ static void _snd_pcm_share_stop(snd_pcm_t *pcm, snd_pcm_state_t state) snd_pcm_areas_silence(pcm->running_areas, 0, pcm->channels, pcm->buffer_size, pcm->format); err = snd_pcm_delay(slave->pcm, &delay); - if (err >= 0 && delay > 0) - snd_pcm_rewind(slave->pcm, delay); + if (err >= 0 && delay > 0) { + int err = snd_pcm_rewind(slave->pcm, delay); + if (err < 0) { + errno = -err; + snd_errornum(PCM, "rewind failed"); + } + } share->drain_silenced = 0; } share->state = state; @@ -1444,7 +1453,7 @@ int snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, const char *sname, pfd.fd = sd[0]; pfd.events = POLLOUT; while ((err = poll(&pfd, 1, 0)) == 1) { - char buf[1]; + char buf[1] = {0}; err = write(sd[0], buf, 1); assert(err != 0); if (err != 1) diff --git a/src/pcm/pcm_shm.c b/src/pcm/pcm_shm.c index c0f904eb..4b176c83 100644 --- a/src/pcm/pcm_shm.c +++ b/src/pcm/pcm_shm.c @@ -323,8 +323,6 @@ static int snd_pcm_shm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) ctrl->u.sw_params = *params; err = snd_pcm_shm_action(pcm); *params = ctrl->u.sw_params; - if (err < 0) - return err; return err; } @@ -437,8 +435,6 @@ static snd_pcm_sframes_t snd_pcm_shm_avail_update(snd_pcm_t *pcm) int err; ctrl->cmd = SND_PCM_IOCTL_AVAIL_UPDATE; err = snd_pcm_shm_action(pcm); - if (err < 0) - return err; return err; } @@ -637,7 +633,7 @@ static int make_local_socket(const char *filename) size_t l = strlen(filename); size_t size = offsetof(struct sockaddr_un, sun_path) + l; struct sockaddr_un *addr = alloca(size); - int sock; + int sock, err; sock = socket(PF_LOCAL, SOCK_STREAM, 0); if (sock < 0) { @@ -649,8 +645,10 @@ static int make_local_socket(const char *filename) memcpy(addr->sun_path, filename, l); if (connect(sock, (struct sockaddr *) addr, size) < 0) { + err = -errno; snd_errornum(PCM, "connect failed"); - return -errno; + close(sock); + return err; } return sock; } @@ -722,6 +720,11 @@ int snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, result = -EINVAL; goto _err; } + if (ans.result < INT_MIN || ans.result > INT_MAX) { + snd_error(PCM, "invalid read"); + result = -EINVAL; + goto _err; + } result = ans.result; if (result < 0) goto _err; @@ -764,7 +767,8 @@ int snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, return 0; _err: - close(sock); + if (sock >= 0) + close(sock); if (ctrl) shmdt(ctrl); free(shm); diff --git a/src/rawmidi/rawmidi_virt.c b/src/rawmidi/rawmidi_virt.c index 75330fd1..09b76179 100644 --- a/src/rawmidi/rawmidi_virt.c +++ b/src/rawmidi/rawmidi_virt.c @@ -181,7 +181,7 @@ static int snd_rawmidi_virtual_drain(snd_rawmidi_t *rmidi) virt->pending = 0; } snd_seq_drain_output(virt->handle); - snd_seq_sync_output_queue(virt->handle); + (void)snd_seq_sync_output_queue(virt->handle); } return snd_rawmidi_virtual_drop(rmidi); } diff --git a/src/rawmidi/ump.c b/src/rawmidi/ump.c index 3ff5fc59..ad252e24 100644 --- a/src/rawmidi/ump.c +++ b/src/rawmidi/ump.c @@ -1099,11 +1099,11 @@ int snd_ump_msg_sysex_expand(const uint32_t *ump, uint8_t *buf, size_t maxlen, */ int snd_ump_packet_length(unsigned int type) { - static int packet_length[16] = { + static unsigned char packet_length[16] = { 1, 1, 1, 2, 2, 4, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4 }; - if (type > 16) + if (type >= sizeof(packet_length)) return 0; return packet_length[type]; } diff --git a/src/seq/seqmid.c b/src/seq/seqmid.c index 604aa2dd..280a27bd 100644 --- a/src/seq/seqmid.c +++ b/src/seq/seqmid.c @@ -476,6 +476,8 @@ int snd_seq_parse_address(snd_seq_t *seq, snd_seq_addr_t *addr, const char *arg) if (!strncmp(arg, cinfo.name, len)) { if (strlen(cinfo.name) == (size_t)len) { /* exact match */ + if (cinfo.client < 0) + return -EIO; addr->client = cinfo.client; return 0; } diff --git a/src/topology/builder.c b/src/topology/builder.c index 8d91b8ef..148c1ab0 100644 --- a/src/topology/builder.c +++ b/src/topology/builder.c @@ -220,13 +220,10 @@ static ssize_t write_manifest_data(snd_tplg_t *tplg) return ret; } - tplg_log(tplg, 'B', tplg->bin_pos, "manifest: write %d bytes", - sizeof(tplg->manifest)); + tplg_log(tplg, 'B', tplg->bin_pos, "manifest: write %zu bytes", sizeof(tplg->manifest)); ret = twrite(tplg, &tplg->manifest, sizeof(tplg->manifest)); if (ret >= 0) { - tplg_log(tplg, 'B', tplg->bin_pos, - "manifest: write %d priv bytes", - tplg->manifest.priv.size); + tplg_log(tplg, 'B', tplg->bin_pos, "manifest: write %d priv bytes", tplg->manifest.priv.size); ret = twrite(tplg, tplg->manifest_pdata, tplg->manifest.priv.size); } return ret; diff --git a/src/topology/ctl.c b/src/topology/ctl.c index 8a84450c..a0c24518 100644 --- a/src/topology/ctl.c +++ b/src/topology/ctl.c @@ -1111,7 +1111,7 @@ int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl, if (enum_ctl->values[i] == NULL) continue; - memcpy(&ec->values[i * sizeof(int) * ENUM_VAL_SIZE], + memcpy(&ec->values[i * ENUM_VAL_SIZE], enum_ctl->values[i], sizeof(int) * ENUM_VAL_SIZE); } diff --git a/src/topology/dapm.c b/src/topology/dapm.c index ac4d6085..d261b15b 100644 --- a/src/topology/dapm.c +++ b/src/topology/dapm.c @@ -329,9 +329,9 @@ done: buf[i] = 0; source = &buf[i + 2]; - strcpy(line->source, source); - strcpy(line->control, control); - strcpy(line->sink, sink); + snd_strlcpy(line->source, source, sizeof(line->source)); + snd_strlcpy(line->control, control, sizeof(line->source)); + snd_strlcpy(line->sink, sink, sizeof(line->source)); return 0; } diff --git a/src/topology/data.c b/src/topology/data.c index 6869e3eb..1753d0c7 100644 --- a/src/topology/data.c +++ b/src/topology/data.c @@ -461,8 +461,7 @@ static int copy_data_hex(char *data, int off, const char *str, int width) return 0; } -static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, - int width) +static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, unsigned int width) { struct snd_soc_tplg_private *priv; const char *value = NULL; @@ -471,11 +470,14 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, tplg_dbg(" data: %s", elem->id); + if (width > 4) + return -EINVAL; + if (snd_config_get_string(cfg, &value) < 0) return -EINVAL; num = get_hex_num(value); - if (num <= 0) { + if (num <= 0 || num > 16384) { snd_error(TOPOLOGY, "malformed hex variable list %s", value); return -EINVAL; } @@ -483,14 +485,16 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, size = num * width; priv = elem->data; - if (size > TPLG_MAX_PRIV_SIZE) { - snd_error(TOPOLOGY, "data too big %d", size); + if (size < 0 || size > TPLG_MAX_PRIV_SIZE) { + snd_error(TOPOLOGY, "data too big %u", (unsigned int)size); return -EINVAL; } if (priv != NULL) { off = priv->size; - esize = elem->size + size; + if (off > 1024*1024) + return -ENOMEM; + esize = off + size; priv = realloc(priv, esize); } else { off = 0; @@ -1696,7 +1700,7 @@ static int tplg_verify_tuple_set(snd_tplg_t *tplg, size_t pos, j = tplg_get_tuple_size(va->type) * va->num_elems; if (j + sizeof(*va) != va->size) { tplg_log(tplg, 'A', pos, "tuple set verify: wrong vendor array size %d " - "(expected %d for %d count %d)", + "(expected %zu for %d count %d)", va->size, j + sizeof(*va), va->type, va->num_elems); return -EINVAL; } diff --git a/src/topology/ops.c b/src/topology/ops.c index b56f6868..13b4719e 100644 --- a/src/topology/ops.c +++ b/src/topology/ops.c @@ -91,6 +91,8 @@ int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, snd_config_t *cfg, if (snd_config_get_string(n, &value) < 0) continue; ival = lookup_ops(value); + if (ival < 0) + return ival; } else { if (tplg_get_integer(n, &ival, 0)) continue; @@ -176,6 +178,8 @@ int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, if (snd_config_get_string(n, &value) < 0) continue; ival = lookup_ops(value); + if (ival < 0) + return ival; } else { if (tplg_get_integer(n, &ival, 0)) continue; diff --git a/src/ucm/main.c b/src/ucm/main.c index 9790565d..fbe71f3e 100644 --- a/src/ucm/main.c +++ b/src/ucm/main.c @@ -189,21 +189,21 @@ static int read_tlv_file(unsigned int **res, goto __fail; } *res = malloc(sz); - if (res == NULL) { + if (*res == NULL) { err = -ENOMEM; goto __fail; } sz_read = read(fd, *res, sz); if (sz_read < 0 || (size_t)sz_read != sz) { err = -EIO; - free(*res); - *res = NULL; + goto __fail_res; } /* Check if the tlv file specifies valid size. */ tlv = (struct snd_ctl_tlv *)(*res); if (tlv->length + 2 * sizeof(unsigned int) != sz) { snd_error(UCM, "Invalid tlv size: %d", tlv->length); err = -EINVAL; +__fail_res: free(*res); *res = NULL; } @@ -715,13 +715,13 @@ static int run_device_all_sequence(snd_use_case_mgr_t *uc_mgr, struct use_case_v struct list_head *pos; int err; - snd_trace(UCM, "disable all devices sequence for '%s'", verb->name); - if (verb == NULL) { snd_error(UCM, "disdevall must be executed inside the verb context"); return -ENOENT; } + snd_trace(UCM, "disable all devices sequence for '%s'", verb->name); + list_for_each(pos, &verb->device_list) { device = list_entry(pos, struct use_case_device, list); @@ -1533,6 +1533,9 @@ int snd_use_case_mgr_open(snd_use_case_mgr_t **uc_mgr, snd_trace(UCM, "{API call} open '%s'", card_name); + if (card_name == NULL) + return -EINVAL; + /* create a new UCM */ mgr = calloc(1, sizeof(snd_use_case_mgr_t)); if (mgr == NULL) @@ -1548,12 +1551,12 @@ int snd_use_case_mgr_open(snd_use_case_mgr_t **uc_mgr, INIT_LIST_HEAD(&mgr->variable_list); pthread_mutex_init(&mgr->mutex, NULL); - if (card_name && *card_name == '-') { + if (*card_name == '-') { card_name++; mgr->suppress_nodev_errors = 1; } - if (card_name && card_name[0] == '<' && card_name[1] == '<' && card_name[2] == '<') + if (card_name[0] == '<' && card_name[1] == '<' && card_name[2] == '<') card_name = parse_open_variables(mgr, card_name); err = uc_mgr_card_open(mgr); @@ -2566,7 +2569,9 @@ static int set_verb_user(snd_use_case_mgr_t *uc_mgr, verb = NULL; } if (uc_mgr->active_verb) { - err = handle_transition_verb(uc_mgr, verb); + err = 0; + if (verb != NULL) + err = handle_transition_verb(uc_mgr, verb); if (err == 0) { err = dismantle_use_case(uc_mgr); if (err < 0) diff --git a/src/ucm/ucm_cond.c b/src/ucm/ucm_cond.c index 5db25d2d..b86d8f04 100644 --- a/src/ucm/ucm_cond.c +++ b/src/ucm/ucm_cond.c @@ -310,7 +310,8 @@ static int if_eval_path(snd_use_case_mgr_t *uc_mgr, snd_config_t *eval) amode = X_OK; } else { snd_error(UCM, "Path unknown mode '%s' (If.Condition.Mode)", s); - free(s); + if (s != mode) + free(s); return -EINVAL; } if (s != mode) diff --git a/src/ucm/ucm_regex.c b/src/ucm/ucm_regex.c index 1f5b84ce..cef23626 100644 --- a/src/ucm/ucm_regex.c +++ b/src/ucm/ucm_regex.c @@ -152,11 +152,12 @@ int uc_mgr_define_regex(snd_use_case_mgr_t *uc_mgr, const char *name, if (err < 0) return err; err = regcomp(&re, s, options); - free(s); if (err) { snd_error(UCM, "Regex '%s' compilation failed (code %d)", s, err); + free(s); return -EINVAL; } + free(s); err = uc_mgr_get_substituted_value(uc_mgr, &s, string); if (err < 0) { diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c index 639dd7a2..73230a2a 100644 --- a/src/ucm/ucm_subs.c +++ b/src/ucm/ucm_subs.c @@ -612,7 +612,7 @@ static char *rval_sysfs_main(snd_use_case_mgr_t *uc_mgr, const char *top_path, c if (s == NULL) return NULL; len = s - id - 1; - if ((size_t)(len - 1) > sizeof(link) - 1) + if ((size_t)len > sizeof(link) - 1) return NULL; strncpy(link, id + 1, len); link[len] = '\0';