Merge lp:~ted/libdbusmenu/proxy-text-fix into lp:libdbusmenu/0.5

Proposed by Ted Gould
Status: Merged
Merged at revision: 251
Proposed branch: lp:~ted/libdbusmenu/proxy-text-fix
Merge into: lp:libdbusmenu/0.5
Diff against target: 66 lines (+20/-3)
2 files modified
libdbusmenu-glib/client.c (+1/-1)
libdbusmenu-glib/menuitem.c (+19/-2)
To merge this branch: bzr merge lp:~ted/libdbusmenu/proxy-text-fix
Reviewer Review Type Date Requested Status
Conor Curran (community) Approve
Review via email: mp+51848@code.launchpad.net

Description of the change

Wow. You're not going to believe it. Basically if you pass a string into remove that is also stored in the hashtable the string will get free'd and written over fast enough that the signal handler sends bad data. That took forever to debug.

To post a comment you must log in.
Revision history for this message
Conor Curran (cjcurran) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'libdbusmenu-glib/client.c'
2--- libdbusmenu-glib/client.c 2011-02-24 14:33:38 +0000
3+++ libdbusmenu-glib/client.c 2011-03-02 03:26:13 +0000
4@@ -1168,7 +1168,7 @@
5 gchar * property;
6
7 while (g_variant_iter_next(&properties, "s", &property)) {
8- g_debug("Removing property '%s' on %d", property, id);
9+ /* g_debug("Removing property '%s' on %d", property, id); */
10 dbusmenu_menuitem_property_remove(menuitem, property);
11 }
12 }
13
14=== modified file 'libdbusmenu-glib/menuitem.c'
15--- libdbusmenu-glib/menuitem.c 2011-03-01 11:15:19 +0000
16+++ libdbusmenu-glib/menuitem.c 2011-03-02 03:26:13 +0000
17@@ -1146,6 +1146,7 @@
18 {
19 g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), FALSE);
20 g_return_val_if_fail(property != NULL, FALSE);
21+ g_return_val_if_fail(g_utf8_validate(property, -1, NULL), FALSE);
22
23 DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
24 GVariant * default_value = NULL;
25@@ -1181,6 +1182,7 @@
26
27
28 gboolean replaced = FALSE;
29+ gboolean remove = FALSE;
30 gpointer currentval = g_hash_table_lookup(priv->properties, property);
31
32 if (value != NULL) {
33@@ -1195,10 +1197,21 @@
34 gchar * lprop = g_strdup(property);
35 g_variant_ref_sink(value);
36
37- g_hash_table_replace(priv->properties, lprop, value);
38+ /* Really important that this is _insert as that means the value
39+ that we just created in the _strdup is free'd and not the one
40+ currently in the hashtable. That could be the same as the one
41+ being passed in and then the signal emit would be done with a
42+ bad value */
43+ g_hash_table_insert(priv->properties, lprop, value);
44 } else {
45 if (currentval != NULL) {
46- g_hash_table_remove(priv->properties, property);
47+ /* So the question you should be asking if you're paying attention
48+ is "Why not just do the remove here?" It's a good question with
49+ an interesting answer. Bascially it's the same reason as above,
50+ in a couple cases the passed in properties is the value in the hash
51+ table so we can avoid strdup'ing it by removing it (and thus free'ing
52+ it) after the signal emition */
53+ remove = TRUE;
54 replaced = TRUE;
55 }
56 }
57@@ -1219,6 +1232,10 @@
58 g_signal_emit(G_OBJECT(mi), signals[PROPERTY_CHANGED], 0, property, signalval, TRUE);
59 }
60
61+ if (remove) {
62+ g_hash_table_remove(priv->properties, property);
63+ }
64+
65 return TRUE;
66 }
67

Subscribers

People subscribed via source and target branches