summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Henningsson <david.henningsson@canonical.com>2015-03-05 14:55:51 +0100
committerDavid Henningsson <david.henningsson@canonical.com>2015-03-11 12:43:02 +0100
commit7b8e8cd3883e081a6e3f2d8ed307524801438e04 (patch)
tree61dde3b7966491ae0670d3997f1a39292d327012
parentebee1a63060f457171eafa93dea63e24264ac8e2 (diff)
pstream: Don't split (non-SHM) memblocks
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@canonical.com>
-rw-r--r--src/pulsecore/pstream.c61
1 files changed, 25 insertions, 36 deletions
diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index b0ed5a70f..877ff66c8 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -682,6 +682,30 @@ fail:
return -1;
}
+static void memblock_complete(pa_pstream *p, struct pstream_read *re) {
+ pa_memchunk chunk;
+ int64_t offset;
+
+ if (!p->receive_memblock_callback)
+ return;
+
+ chunk.memblock = re->memblock;
+ chunk.index = 0;
+ chunk.length = re->index - PA_PSTREAM_DESCRIPTOR_SIZE;
+
+ 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 +855,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);