[pulseaudio-discuss] [PATCH 1/3] pstream: Don't split (non-SHM) memblocks

Peter Meerwald pmeerw at pmeerw.net
Fri Mar 6 12:20:02 PST 2015


On Thu, 5 Mar 2015, David Henningsson wrote:

> In case SHM is full or disabled, audio data is sent through the
> io/srbchannel. When this channel in turn gets full, memblocks
> could previously be split up. This could lead to crashes in case
> the split was on non-frame boundaries (in combination with full
> memblock queues).
> 
> BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=88452
> Signed-off-by: David Henningsson <david.henningsson at canonical.com>
> ---
>  src/pulsecore/pstream.c | 67 +++++++++++++++++++++++--------------------------
>  1 file changed, 31 insertions(+), 36 deletions(-)
> 
> diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
> index b0ed5a7..8c05a87 100644
> --- a/src/pulsecore/pstream.c
> +++ b/src/pulsecore/pstream.c
> @@ -682,6 +682,36 @@ fail:
>      return -1;
>  }
>  
> +static void memblock_complete(pa_pstream *p, struct pstream_read *re) {
> +    size_t l;
> +    pa_memchunk chunk;
> +    int64_t offset;
> +
> +    if (!p->receive_memblock_callback)
> +        return;
> +
> +    /* Is this memblock data? Then pass it to the user */
> +    l = re->index - PA_PSTREAM_DESCRIPTOR_SIZE;
> +    if (l <= 0)

l is an unsigned data type; the difference should not become negative and 
the check should just be for (l == 0)

> +        return;
> +
> +    chunk.memblock = re->memblock;
> +    chunk.index = 0;
> +    chunk.length = l;
> +
> +    offset = (int64_t) (
> +             (((uint64_t) ntohl(re->descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])) << 32) |
> +             (((uint64_t) ntohl(re->descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO]))));
> +
> +    p->receive_memblock_callback(
> +        p,
> +        ntohl(re->descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]),
> +        offset,
> +        ntohl(re->descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS]) & PA_FLAG_SEEKMASK,
> +        &chunk,
> +        p->receive_memblock_callback_userdata);
> +}
> +
>  static int do_read(pa_pstream *p, struct pstream_read *re) {
>      void *d;
>      size_t l;
> @@ -831,47 +861,12 @@ static int do_read(pa_pstream *p, struct pstream_read *re) {
>          }
>  
>      } else if (re->index > PA_PSTREAM_DESCRIPTOR_SIZE) {
> -        /* Frame payload available */
> -
> -        if (re->memblock && p->receive_memblock_callback) {
> -
> -            /* Is this memblock data? Than pass it to the user */
> -            l = (re->index - (size_t) r) < PA_PSTREAM_DESCRIPTOR_SIZE ? (size_t) (re->index - PA_PSTREAM_DESCRIPTOR_SIZE) : (size_t) r;
> -
> -            if (l > 0) {
> -                pa_memchunk chunk;
> -
> -                chunk.memblock = re->memblock;
> -                chunk.index = re->index - PA_PSTREAM_DESCRIPTOR_SIZE - l;
> -                chunk.length = l;
> -
> -                if (p->receive_memblock_callback) {
> -                    int64_t offset;
> -
> -                    offset = (int64_t) (
> -                            (((uint64_t) ntohl(re->descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])) << 32) |
> -                            (((uint64_t) ntohl(re->descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO]))));
> -
> -                    p->receive_memblock_callback(
> -                        p,
> -                        ntohl(re->descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]),
> -                        offset,
> -                        ntohl(re->descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS]) & PA_FLAG_SEEKMASK,
> -                        &chunk,
> -                        p->receive_memblock_callback_userdata);
> -                }
> -
> -                /* Drop seek info for following callbacks */
> -                re->descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS] =
> -                    re->descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] =
> -                    re->descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO] = 0;
> -            }
> -        }
>  
>          /* Frame complete */
>          if (re->index >= ntohl(re->descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) + PA_PSTREAM_DESCRIPTOR_SIZE) {
>  
>              if (re->memblock) {
> +                memblock_complete(p, re);
>  
>                  /* This was a memblock frame. We can unref the memblock now */
>                  pa_memblock_unref(re->memblock);
> -- 
> 1.9.1
> 
> _______________________________________________
> pulseaudio-discuss mailing list
> pulseaudio-discuss at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss
> 

-- 

Peter Meerwald
+43-664-2444418 (mobile)


More information about the pulseaudio-discuss mailing list