summaryrefslogtreecommitdiffstats
path: root/server/red_parse_qxl.c
diff options
context:
space:
mode:
authorFrediano Ziglio <fziglio@redhat.com>2015-09-08 12:14:55 +0100
committerFrediano Ziglio <fziglio@redhat.com>2015-10-06 11:11:11 +0100
commitf3605979ce3b33d60c33b59334b53618e6d8662a (patch)
tree1bc1b66171edcb9852c7e45508bd5616a9dedd59 /server/red_parse_qxl.c
parent3738478ed7065fe05f3ee4848f8a7fcdf40aa920 (diff)
downloadspice-f3605979ce3b33d60c33b59334b53618e6d8662a.tar.gz
spice-f3605979ce3b33d60c33b59334b53618e6d8662a.tar.xz
spice-f3605979ce3b33d60c33b59334b53618e6d8662a.zip
Prevent memory leak if red_get_data_chunks_ptr fails
Free linked list if client tries to do nasty things Signed-off-by: Frediano Ziglio <fziglio@redhat.com> Acked-by: Christophe Fergeau <cfergeau@redhat.com>
Diffstat (limited to 'server/red_parse_qxl.c')
-rw-r--r--server/red_parse_qxl.c31
1 files changed, 20 insertions, 11 deletions
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index 2863ae26..f4258697 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -107,34 +107,43 @@ static size_t red_get_data_chunks_ptr(RedMemSlotInfo *slots, int group_id,
red->data_size = qxl->data_size;
data_size += red->data_size;
red->data = qxl->data;
+ red->prev_chunk = red->next_chunk = NULL;
if (!validate_virt(slots, (intptr_t)red->data, memslot_id, red->data_size, group_id)) {
red->data = NULL;
return 0;
}
- red->prev_chunk = NULL;
while ((next_chunk = qxl->next_chunk) != 0) {
red_prev = red;
- red = spice_new(RedDataChunk, 1);
+ red = spice_new0(RedDataChunk, 1);
+ red->prev_chunk = red_prev;
+ red_prev->next_chunk = red;
+
memslot_id = get_memslot_id(slots, next_chunk);
qxl = (QXLDataChunk *)get_virt(slots, next_chunk, sizeof(*qxl), group_id,
&error);
- if (error) {
- return 0;
- }
+ if (error)
+ goto error;
red->data_size = qxl->data_size;
data_size += red->data_size;
red->data = qxl->data;
- if (!validate_virt(slots, (intptr_t)red->data, memslot_id, red->data_size, group_id)) {
- red->data = NULL;
- return 0;
- }
- red->prev_chunk = red_prev;
- red_prev->next_chunk = red;
+ if (!validate_virt(slots, (intptr_t)red->data, memslot_id, red->data_size, group_id))
+ goto error;
}
red->next_chunk = NULL;
return data_size;
+
+error:
+ while (red->prev_chunk) {
+ red_prev = red->prev_chunk;
+ free(red);
+ red = red_prev;
+ }
+ red->data_size = 0;
+ red->next_chunk = NULL;
+ red->data = NULL;
+ return 0;
}
static size_t red_get_data_chunks(RedMemSlotInfo *slots, int group_id,