summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYonit Halperin <yhalperi@redhat.com>2011-07-12 08:50:34 +0300
committerAlon Levy <alevy@redhat.com>2011-07-21 15:09:28 +0300
commit4c44be35b05670051d240ff2877940cef3d9b18c (patch)
tree0852f9ccd11e8bcd702c031396b7b8a1643f37ba
parente22354141e6b2cfdc71380e0815ff52d7f5131f6 (diff)
downloadspice-4c44be35b05670051d240ff2877940cef3d9b18c.tar.gz
spice-4c44be35b05670051d240ff2877940cef3d9b18c.tar.xz
spice-4c44be35b05670051d240ff2877940cef3d9b18c.zip
server: fix access to a released drawable. RHBZ #713474
red_pipe_add_drawable can lead to removal of drawables from current tree (since it calls red_handle_drawable_surfaces_client_synced), which can also lead to releasing these drawables. Before the fix, red_current_add_equal, called red_pipe_add_drawable, without assuring afterwards that the drawables it refers to are still alive or still in the current tree.
-rw-r--r--server/red_worker.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/server/red_worker.c b/server/red_worker.c
index 72bdc31c..45686963 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -2817,22 +2817,29 @@ static inline int red_current_add_equal(RedWorker *worker, DrawItem *item, TreeI
int add_after = !!other_drawable->stream && is_drawable_independent_from_surfaces(drawable);
red_stream_maintenance(worker, drawable, other_drawable);
__current_add_drawable(worker, drawable, &other->siblings_link);
+ other_drawable->refs++;
+ current_remove_drawable(worker, other_drawable);
if (add_after) {
red_pipe_add_drawable_after(worker, drawable, other_drawable);
} else {
red_pipe_add_drawable(worker, drawable);
}
- remove_drawable(worker, other_drawable);
+ red_pipe_remove_drawable(worker, other_drawable);
+ release_drawable(worker, other_drawable);
return TRUE;
}
switch (item->effect) {
case QXL_EFFECT_REVERT_ON_DUP:
if (is_same_drawable(worker, drawable, other_drawable)) {
+ other_drawable->refs++;
+ current_remove_drawable(worker, other_drawable);
if (!ring_item_is_linked(&other_drawable->pipe_item.link)) {
red_pipe_add_drawable(worker, drawable);
+ } else {
+ red_pipe_remove_drawable(worker, other_drawable);
}
- remove_drawable(worker, other_drawable);
+ release_drawable(worker, other_drawable);
return TRUE;
}
break;