On Thu, 11 Apr 2002, Sander van Leeuwen wrote:

> Hi,
> 
> I'm currently porting ALSA to OS/2 and have encountered a bug in
> snd_pcm_playback_silence (core\pcm_lib.c)
> While playing an 8 bits stereo 44.1khz wave file the system
> would trap when stopping the stream. The cause was heap
> corruption caused by this function. There is no check to
> see if the offset + amount of frames to silence is larger
> than the buffer size.
> The patch below fixes this.
> 
> Sander
> 
> 
> 
> --- E:\Development\ALSA.Linux\alsa-kernel\core\pcm_lib.c      Wed Apr 10 21:55:18 
>2002
> +++ E:\Development\ALSA.OS2\GPL\alsa\core\pcm_lib.c   Thu Apr 11 17:01:38 2002
> @@ -60,6 +56,12 @@
>       ofs = runtime->silenced_start % runtime->buffer_size + runtime->silenced_size;
>       if (ofs >= runtime->buffer_size)
>               ofs -= runtime->buffer_size;
> +#ifdef TARGET_OS2
> +        if (ofs + frames > runtime->buffer_size) {
> +                frames = runtime->buffer_size - ofs;
> +        }
> +#endif
>       if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
>           runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
>               if (substream->ops->silence) {

Above patch is not perfect, but thank you for pointing to this problem. 
I've applied this fix to CVS:

Index: pcm_lib.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/core/pcm_lib.c,v
retrieving revision 1.9
diff -u -r1.9 pcm_lib.c
--- pcm_lib.c   9 Apr 2002 06:53:35 -0000       1.9
+++ pcm_lib.c   12 Apr 2002 07:04:47 -0000
@@ -34,7 +34,7 @@
 void snd_pcm_playback_silence(snd_pcm_substream_t *substream)
 {
        snd_pcm_runtime_t *runtime = substream->runtime;
-       snd_pcm_uframes_t frames, ofs;
+       snd_pcm_uframes_t frames, ofs, transfer;
        snd_pcm_sframes_t noise_dist;
        if (runtime->silenced_start != runtime->control->appl_ptr) {
                snd_pcm_sframes_t n = runtime->control->appl_ptr - 
runtime->silenced_start;
@@ -60,32 +60,36 @@
        ofs = runtime->silenced_start % runtime->buffer_size + runtime->silenced_size;
        if (ofs >= runtime->buffer_size)
                ofs -= runtime->buffer_size;
-       if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
-           runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-               if (substream->ops->silence) {
-                       int err;
-                       err = substream->ops->silence(substream, -1, ofs, frames);
-                       snd_assert(err >= 0, );
-               } else {
-                       char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, 
ofs);
-                       snd_pcm_format_set_silence(runtime->format, hwbuf, frames * 
runtime->channels);
-               }
-       } else {
-               unsigned int c;
-               unsigned int channels = runtime->channels;
-               if (substream->ops->silence) {
-                       for (c = 0; c < channels; ++c) {
+       while (frames > 0) {
+               transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size 
+- ofs : frames;
+               if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
+                   runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
+                       if (substream->ops->silence) {
                                int err;
-                               err = substream->ops->silence(substream, c, ofs, 
frames);
+                               err = substream->ops->silence(substream, -1, ofs, 
+transfer);
                                snd_assert(err >= 0, );
+                       } else {
+                               char *hwbuf = runtime->dma_area + 
+frames_to_bytes(runtime, ofs);
+                               snd_pcm_format_set_silence(runtime->format, hwbuf, 
+transfer * runtime->channels);
                        }
                } else {
-                       size_t dma_csize = runtime->dma_bytes / channels;
-                       for (c = 0; c < channels; ++c) {
-                               char *hwbuf = runtime->dma_area + (c * dma_csize) + 
samples_to_bytes(runtime, ofs);
-                               snd_pcm_format_set_silence(runtime->format, hwbuf, 
frames);
+                       unsigned int c;
+                       unsigned int channels = runtime->channels;
+                       if (substream->ops->silence) {
+                               for (c = 0; c < channels; ++c) {
+                                       int err;
+                                       err = substream->ops->silence(substream, c, 
+ofs, transfer);
+                                       snd_assert(err >= 0, );
+                               }
+                       } else {
+                               size_t dma_csize = runtime->dma_bytes / channels;
+                               for (c = 0; c < channels; ++c) {
+                                       char *hwbuf = runtime->dma_area + (c * 
+dma_csize) + samples_to_bytes(runtime, ofs);
+                                       snd_pcm_format_set_silence(runtime->format, 
+hwbuf, transfer);
+                               }
                        }
                }
+               frames -= transfer;
        }
        runtime->silenced_size += frames;
 }


                                                Jaroslav

-----
Jaroslav Kysela <[EMAIL PROTECTED]>
Linux Kernel Sound Maintainer
ALSA Project  http://www.alsa-project.org
SuSE Linux    http://www.suse.com


_______________________________________________
Alsa-devel mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-devel

Reply via email to