]> git.alsa-project.org Git - alsa-lib.git/commitdiff
pcm: dshare: Fix segfault when not binding channel 0
authorKirill Marinushkin <kmarinushkin@birdec.tech>
Tue, 20 Nov 2018 20:43:44 +0000 (21:43 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 21 Nov 2018 10:01:21 +0000 (11:01 +0100)
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 <kmarinushkin@birdec.tech>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
src/pcm/pcm_dshare.c

index 54dc9d4858afbcc167b97bc4cca6be890729c4bf..2bb735fe1b467b37d5e8f957d2f15f800360b37f 100644 (file)
@@ -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<<dshare->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;