Blame SOURCES/0051-Prevent-memory-leak-if-red_get_data_chunks_ptr-fails.patch

73b8f2
From 173645bea63ad31ba0d6d4c58a06272aa488fb92 Mon Sep 17 00:00:00 2001
73b8f2
From: Frediano Ziglio <fziglio@redhat.com>
73b8f2
Date: Tue, 8 Sep 2015 12:14:55 +0100
73b8f2
Subject: [PATCH 51/57] Prevent memory leak if red_get_data_chunks_ptr fails
73b8f2
73b8f2
Free linked list if client tries to do nasty things
73b8f2
73b8f2
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
73b8f2
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
73b8f2
---
73b8f2
 server/red_parse_qxl.c | 31 ++++++++++++++++++++-----------
73b8f2
 1 file changed, 20 insertions(+), 11 deletions(-)
73b8f2
73b8f2
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
73b8f2
index 7cc20e6..fe3ae78 100644
73b8f2
--- a/server/red_parse_qxl.c
73b8f2
+++ b/server/red_parse_qxl.c
73b8f2
@@ -107,34 +107,43 @@ static size_t red_get_data_chunks_ptr(RedMemSlotInfo *slots, int group_id,
73b8f2
     red->data_size = qxl->data_size;
73b8f2
     data_size += red->data_size;
73b8f2
     red->data = qxl->data;
73b8f2
+    red->prev_chunk = red->next_chunk = NULL;
73b8f2
     if (!validate_virt(slots, (intptr_t)red->data, memslot_id, red->data_size, group_id)) {
73b8f2
         red->data = NULL;
73b8f2
         return 0;
73b8f2
     }
73b8f2
-    red->prev_chunk = NULL;
73b8f2
 
73b8f2
     while ((next_chunk = qxl->next_chunk) != 0) {
73b8f2
         red_prev = red;
73b8f2
-        red = spice_new(RedDataChunk, 1);
73b8f2
+        red = spice_new0(RedDataChunk, 1);
73b8f2
+        red->prev_chunk = red_prev;
73b8f2
+        red_prev->next_chunk = red;
73b8f2
+
73b8f2
         memslot_id = get_memslot_id(slots, next_chunk);
73b8f2
         qxl = (QXLDataChunk *)get_virt(slots, next_chunk, sizeof(*qxl), group_id,
73b8f2
                                       &error);
73b8f2
-        if (error) {
73b8f2
-            return 0;
73b8f2
-        }
73b8f2
+        if (error)
73b8f2
+            goto error;
73b8f2
         red->data_size = qxl->data_size;
73b8f2
         data_size += red->data_size;
73b8f2
         red->data = qxl->data;
73b8f2
-        if (!validate_virt(slots, (intptr_t)red->data, memslot_id, red->data_size, group_id)) {
73b8f2
-            red->data = NULL;
73b8f2
-            return 0;
73b8f2
-        }
73b8f2
-        red->prev_chunk = red_prev;
73b8f2
-        red_prev->next_chunk = red;
73b8f2
+        if (!validate_virt(slots, (intptr_t)red->data, memslot_id, red->data_size, group_id))
73b8f2
+            goto error;
73b8f2
     }
73b8f2
 
73b8f2
     red->next_chunk = NULL;
73b8f2
     return data_size;
73b8f2
+
73b8f2
+error:
73b8f2
+    while (red->prev_chunk) {
73b8f2
+        red_prev = red->prev_chunk;
73b8f2
+        free(red);
73b8f2
+        red = red_prev;
73b8f2
+    }
73b8f2
+    red->data_size = 0;
73b8f2
+    red->next_chunk = NULL;
73b8f2
+    red->data = NULL;
73b8f2
+    return 0;
73b8f2
 }
73b8f2
 
73b8f2
 static size_t red_get_data_chunks(RedMemSlotInfo *slots, int group_id,
73b8f2
-- 
73b8f2
2.4.3
73b8f2