mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-11-07 13:30:07 -05:00
pcm: fix and optimize snd_pcm_areas_copy function
The memcpy() function in snd_pcm_area_copy() should not be called with the overlapped areas. Alex discovered - using own LD_PRELOAD checked for memcpy() input - that the memcpy() is called with src == dst. For some special plugin combos (rate+softvol+hw for example), the same areas with same offsets can be asked to be copied (softvol). The collapse check uses own areas created on heap, causing dst_area == src_area && dst_offset == src_offset check bypassed. Two fixes are in this patch: - use assert to check the memcpy() input for future triggers - bypass the snd_pcm_area_copy() call for collapsed identical areas Reported-by: Alexander Kruppa <akruppa@gmail.com> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
28493d9d69
commit
009193a345
1 changed files with 17 additions and 11 deletions
|
|
@ -2711,6 +2711,8 @@ int snd_pcm_area_copy(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes_t
|
||||||
dst_area->step == (unsigned int) width) {
|
dst_area->step == (unsigned int) width) {
|
||||||
size_t bytes = samples * width / 8;
|
size_t bytes = samples * width / 8;
|
||||||
samples -= bytes * 8 / width;
|
samples -= bytes * 8 / width;
|
||||||
|
assert(src < dst || src >= dst + bytes);
|
||||||
|
assert(dst < src || dst >= src + bytes);
|
||||||
memcpy(dst, src, bytes);
|
memcpy(dst, src, bytes);
|
||||||
if (samples == 0)
|
if (samples == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -2845,17 +2847,21 @@ int snd_pcm_areas_copy(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (chns > 1 && chns * width == step) {
|
if (chns > 1 && chns * width == step) {
|
||||||
/* Collapse the areas */
|
if (src_offset != dst_offset ||
|
||||||
snd_pcm_channel_area_t s, d;
|
src_start->addr != dst_start->addr ||
|
||||||
s.addr = src_start->addr;
|
src_start->first != dst_start->first) {
|
||||||
s.first = src_start->first;
|
/* Collapse the areas */
|
||||||
s.step = width;
|
snd_pcm_channel_area_t s, d;
|
||||||
d.addr = dst_start->addr;
|
s.addr = src_start->addr;
|
||||||
d.first = dst_start->first;
|
s.first = src_start->first;
|
||||||
d.step = width;
|
s.step = width;
|
||||||
snd_pcm_area_copy(&d, dst_offset * chns,
|
d.addr = dst_start->addr;
|
||||||
&s, src_offset * chns,
|
d.first = dst_start->first;
|
||||||
frames * chns, format);
|
d.step = width;
|
||||||
|
snd_pcm_area_copy(&d, dst_offset * chns,
|
||||||
|
&s, src_offset * chns,
|
||||||
|
frames * chns, format);
|
||||||
|
}
|
||||||
channels -= chns;
|
channels -= chns;
|
||||||
} else {
|
} else {
|
||||||
snd_pcm_area_copy(dst_start, dst_offset,
|
snd_pcm_area_copy(dst_start, dst_offset,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue