Package: at-spi2-atk / 2.22.0-2

git-8d3cc68f7bc62c7015d986212be0d5d776920ee2 Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
commit 8d3cc68f7bc62c7015d986212be0d5d776920ee2
Author: Milan Crha <mcrha@redhat.com>
Date:   Mon May 8 17:21:58 2017 -0500

    Fix use after free when returned objects hold only one ref
    
    It seems that not all code expects atk_object_ref_accessible_child()
    returning NULL, neither that it can return an object with only one
    reference, thus the following unref in the code can cause use-after-free
    eventually.
    
    At least the chunk in impl_GetChildAtIndex() avoids runtime warning about
    invalid object being passed to g_object_unref(), which happened, in this
    case, when evolution returned NULL. Evolution returns objects with one
    reference only often, which tries to address the other chunks here.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=781716

diff --git a/atk-adaptor/adaptors/accessible-adaptor.c b/atk-adaptor/adaptors/accessible-adaptor.c
index 058b116..572e4f8 100644
--- a/atk-adaptor/adaptors/accessible-adaptor.c
+++ b/atk-adaptor/adaptors/accessible-adaptor.c
@@ -182,7 +182,8 @@ impl_GetChildAtIndex (DBusConnection * bus,
     }
   child = atk_object_ref_accessible_child (object, i);
   reply = spi_object_return_reference (message, child);
-  g_object_unref (child);
+  if (child)
+    g_object_unref (child);
 
   return reply;
 }
diff --git a/atk-adaptor/adaptors/collection-adaptor.c b/atk-adaptor/adaptors/collection-adaptor.c
index 42ea073..b57c5f6 100644
--- a/atk-adaptor/adaptors/collection-adaptor.c
+++ b/atk-adaptor/adaptors/collection-adaptor.c
@@ -494,9 +494,12 @@ sort_order_canonical (MatchRulePrivate * mrp, GList * ls,
     {
       AtkObject *child = atk_object_ref_accessible_child (obj, i);
 
-      g_object_unref (child);
+      if (!child)
+        continue;
+
       if (prev && child == pobj)
         {
+          g_object_unref (child);
           return kount;
         }
 
@@ -517,6 +520,7 @@ sort_order_canonical (MatchRulePrivate * mrp, GList * ls,
         kount = sort_order_canonical (mrp, ls, kount,
                                       max, child, 0, TRUE,
                                       pobj, recurse, traverse);
+      g_object_unref (child);
     }
   return kount;
 }
@@ -559,19 +563,23 @@ sort_order_rev_canonical (MatchRulePrivate * mrp, GList * ls,
          and get it's last descendant.
          First, get the previous sibling */
       nextobj = atk_object_ref_accessible_child (parent, indexinparent - 1);
-      g_object_unref (nextobj);
 
       /* Now, drill down the right side to the last descendant */
-      while (atk_object_get_n_accessible_children (nextobj) > 0)
+      while (nextobj && atk_object_get_n_accessible_children (nextobj) > 0)
         {
-          nextobj = atk_object_ref_accessible_child (nextobj,
+	  AtkObject *follow;
+
+          follow = atk_object_ref_accessible_child (nextobj,
                                                      atk_object_get_n_accessible_children
                                                      (nextobj) - 1);
           g_object_unref (nextobj);
+	  nextobj = follow;
         }
       /* recurse with the last descendant */
       kount = sort_order_rev_canonical (mrp, ls, kount, max,
                                         nextobj, TRUE, pobj);
+      if (nextobj)
+	 g_object_unref (nextobj);
     }
   else if (max == 0 || kount < max)
     {