diff options
author | Frediano Ziglio <fziglio@redhat.com> | 2015-09-08 12:14:55 +0100 |
---|---|---|
committer | Frediano Ziglio <fziglio@redhat.com> | 2015-10-06 11:11:11 +0100 |
commit | f3605979ce3b33d60c33b59334b53618e6d8662a (patch) | |
tree | 1bc1b66171edcb9852c7e45508bd5616a9dedd59 /server/red_parse_qxl.c | |
parent | 3738478ed7065fe05f3ee4848f8a7fcdf40aa920 (diff) | |
download | spice-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.c | 31 |
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, |