From: Kirill Marinushkin Date: Tue, 20 Nov 2018 20:43:44 +0000 (+0100) Subject: pcm: dshare: Fix segfault when not binding channel 0 X-Git-Tag: v1.1.8~22 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=d3dfef24bf47b0556deed9686d62a0255cace7e8;p=alsa-lib.git pcm: dshare: Fix segfault when not binding channel 0 Configuration to reproduce: ~~~~ pcm.share_right { type dshare ipc_key 73 ipc_perm 0666 slave { pcm "hw:0,0" } bindings { # the seagfault happens when we don't bind channel 0 1 1 } } ~~~~ Execute to reproduce: ~~~~ $ aplay -D plug:share_right test.wav Playing WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo Segmentation fault ~~~~ For channels whithout binding, values are set to UINT_MAX in function `snd_pcm_direct_parse_bindings()`: ~~~~ for (chn = 0; chn < count; chn++) bindings[chn] = UINT_MAX; /* don't route */ ~~~~ But, these values are not checked when playing, which causes the segfault. This commit fixes the issue. Signed-off-by: Kirill Marinushkin Signed-off-by: Takashi Iwai --- diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c index 54dc9d48..2bb735fe 100644 --- a/src/pcm/pcm_dshare.c +++ b/src/pcm/pcm_dshare.c @@ -67,7 +67,9 @@ static void do_silence(snd_pcm_t *pcm) format = dshare->shmptr->s.format; for (chn = 0; chn < channels; chn++) { dchn = dshare->bindings ? dshare->bindings[chn] : chn; - snd_pcm_area_silence(&dst_areas[dchn], 0, dshare->shmptr->s.buffer_size, format); + if (dchn != UINT_MAX) + snd_pcm_area_silence(&dst_areas[dchn], 0, + dshare->shmptr->s.buffer_size, format); } } @@ -91,7 +93,9 @@ static void share_areas(snd_pcm_direct_t *dshare, } else { for (chn = 0; chn < channels; chn++) { dchn = dshare->bindings ? dshare->bindings[chn] : chn; - snd_pcm_area_copy(&dst_areas[dchn], dst_ofs, &src_areas[chn], src_ofs, size, format); + if (dchn != UINT_MAX) + snd_pcm_area_copy(&dst_areas[dchn], dst_ofs, + &src_areas[chn], src_ofs, size, format); } } @@ -834,8 +838,11 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, dshare->spcm = spcm; } - for (chn = 0; chn < dshare->channels; chn++) - dshare->u.dshare.chn_mask |= (1ULL<bindings[chn]); + for (chn = 0; chn < dshare->channels; chn++) { + unsigned int dchn = dshare->bindings ? dshare->bindings[chn] : chn; + if (dchn != UINT_MAX) + dshare->u.dshare.chn_mask |= (1ULL << dchn); + } if (dshare->shmptr->u.dshare.chn_mask & dshare->u.dshare.chn_mask) { SNDERR("destination channel specified in bindings is already used"); dshare->u.dshare.chn_mask = 0;