Merge lp:~compiz-team/compiz/compiz.fix_1018602 into lp:compiz/0.9.8

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp:~compiz-team/compiz/compiz.fix_1018602
Merge into: lp:compiz/0.9.8
Diff against target: 392 lines (+89/-91)
1 file modified
compizconfig/gsettings/src/gsettings.c (+89/-91)
To merge this branch: bzr merge lp:~compiz-team/compiz/compiz.fix_1018602
Reviewer Review Type Date Requested Status
Daniel van Vugt Needs Fixing
Review via email: mp+112502@code.launchpad.net

This proposal supersedes a proposal from 2012-06-27.

This proposal has been superseded by a proposal from 2012-06-29.

Description of the change

Fixes LP (#1018602) : An invalid read when using g_variant_iter_loop.

No tests yet, tests will be added to gsettings in another commit when the lcc testing work lands.

To post a comment you must log in.
Revision history for this message
Daniel van Vugt (vanvugt) : Posted in a previous version of this proposal
review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Oops. There is a problem under case TypeMatch:
array is no longer initialized with zeros because you changed calloc to malloc. So the free() loop after it could potentially free an invalid pointer if g_variant_iter_loop doesn't find exactly nItems.

Also, strdup(value) is not necessary if you use:
     while (g_variant_iter_next (iter, "s", &value))
  *arrayCounter++ = value;
and then change the free() calls below it to g_free().

On that note, the variable variantType should be removed from readListValue. Just use "s", "i", "b" and "d" instead. It will be smaller, faster and more readable.

review: Needs Fixing
Revision history for this message
Sam Spilsbury (smspillaz) wrote :

Coolio, fixed the calloc issue, plugged a few other memleaks and fixed some gvariant errors I noticed.

I abstracted out the variantType stuff into a function - it should probably be transparent to the user as to the implementation detail of having to pass an arbitrary string to g_variant_get

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

Thanks for the tip on using g_variant_iter_next ... that's now fixed too.

3266. By Sam Spilsbury

Use g_variant_iter_next if we don't require the read out value to be free'd immediately

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

The addition of compizconfigTypeToVariantType makes no sense.

We already have a tight coupling between:
    TYPE x;
and:
    g_variant_iter_loop (&iter, TYPESTRING, &x)

Using:
    g_variant_iter_loop (&iter, someVariable, &x)
only makes the code harder to read, with looser coupling and weaker cohesion.

Please remove compizconfigTypeToVariantType and just use:
    g_variant_iter_loop (&iter, "X", &x)

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

It's the same as:
    printf(secretFormatString, x, y, z);
It's too hard to read so adds maintenance risk.

Everyone would much prefer to read:
    printf("The results are: %d %s %f\n", x, y, z);

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

I think the printf analogy in this case doesn't apply here, the type string is merely an implementation detail - we know from the code what we want to extract already, and the type string is there to operate the valist API.

In any case, I'll change it.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Maybe. But back to the actual case of g_variant_iter_loop(I, F, V)... F and V are tightly coupled and need to match up so you should see the explicit value of F and type of V within the same block of code...

int v;
g_variant_iter_loop(&x, "i", &v)

3267. By Sam Spilsbury

Remove variantType and just specify the string

3268. By Sam Spilsbury

Plug memleak, s/g_free/free and s/"f"/"d"/

3269. By Sam Spilsbury

use g_strfreev

3270. By Sam Spilsbury

Merge lp:compiz

3271. By Sam Spilsbury

Plug other memleaks.

3272. By Sam Spilsbury

Merge lp:compiz

Unmerged revisions

3272. By Sam Spilsbury

Merge lp:compiz

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'compizconfig/gsettings/src/gsettings.c'
2--- compizconfig/gsettings/src/gsettings.c 2012-05-21 15:37:47 +0000
3+++ compizconfig/gsettings/src/gsettings.c 2012-06-29 02:02:20 +0000
4@@ -33,6 +33,31 @@
5
6 #include "gsettings.h"
7
8+static gboolean
9+compizconfigTypeHasVariantType (CCSSettingType type)
10+{
11+ gint i = 0;
12+
13+ static const unsigned int nVariantTypes = 6;
14+ static const CCSSettingType variantTypes[] =
15+ {
16+ TypeString,
17+ TypeMatch,
18+ TypeColor,
19+ TypeBool,
20+ TypeInt,
21+ TypeFloat
22+ };
23+
24+ for (; i < nVariantTypes; i++)
25+ {
26+ if (variantTypes[i] == type)
27+ return TRUE;
28+ }
29+
30+ return FALSE;
31+}
32+
33 static void
34 valueChanged (GSettings *settings,
35 gchar *keyname,
36@@ -122,10 +147,11 @@
37 GList *l = settingsList;
38 gchar *schemaName = getSchemaNameForPlugin (plugin);
39 GVariant *writtenPlugins;
40+ gsize writtenPluginsLen;
41+ gsize newWrittenPluginsSize;
42+ gchar **newWrittenPlugins;
43 char *plug;
44- GVariant *newWrittenPlugins;
45- GVariantBuilder *newWrittenPluginsBuilder;
46- GVariantIter *iter;
47+ GVariantIter iter;
48 gboolean found = FALSE;
49
50 while (l)
51@@ -163,26 +189,31 @@
52
53 writtenPlugins = g_settings_get_value (currentProfileSettings, "plugins-with-set-keys");
54
55- newWrittenPluginsBuilder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
56+ g_variant_iter_init (&iter, writtenPlugins);
57+ newWrittenPluginsSize = g_variant_iter_n_children (&iter);
58
59- iter = g_variant_iter_new (writtenPlugins);
60- while (g_variant_iter_loop (iter, "s", &plug))
61+ while (g_variant_iter_loop (&iter, "s", &plug))
62 {
63- g_variant_builder_add (newWrittenPluginsBuilder, "s", plug);
64-
65 if (!found)
66 found = (g_strcmp0 (plug, plugin) == 0);
67 }
68
69 if (!found)
70- g_variant_builder_add (newWrittenPluginsBuilder, "s", plugin);
71-
72- newWrittenPlugins = g_variant_new ("as", newWrittenPluginsBuilder);
73- g_settings_set_value (currentProfileSettings, "plugins-with-set-keys", newWrittenPlugins);
74-
75- g_variant_iter_free (iter);
76- g_variant_unref (newWrittenPlugins);
77- g_variant_builder_unref (newWrittenPluginsBuilder);
78+ newWrittenPluginsSize++;
79+
80+ newWrittenPlugins = g_variant_dup_strv (writtenPlugins, &writtenPluginsLen);
81+
82+ if (writtenPluginsLen > newWrittenPluginsSize)
83+ {
84+ newWrittenPlugins = g_realloc (newWrittenPlugins, (newWrittenPluginsSize + 1) * sizeof (gchar *));
85+ newWrittenPlugins[writtenPluginsLen + 1] = g_strdup (plugin);
86+ newWrittenPlugins[newWrittenPluginsSize] = NULL;
87+ }
88+
89+ g_settings_set_strv (currentProfileSettings, "plugins-with-set-keys", (const gchar * const *)newWrittenPlugins);
90+
91+ g_free (schemaName);
92+ g_strfreev (newWrittenPlugins);
93
94 return settingsObj;
95 }
96@@ -277,36 +308,17 @@
97 readListValue (CCSSetting *setting)
98 {
99 GSettings *settings = getSettingsObjectForCCSSetting (setting);
100- gchar *variantType;
101+ gboolean hasVariantType;
102 unsigned int nItems, i = 0;
103 CCSSettingValueList list = NULL;
104 GVariant *value;
105- GVariantIter *iter;
106+ GVariantIter iter;
107
108 char *cleanSettingName = translateKeyForGSettings (setting->name);
109
110- switch (setting->info.forList.listType)
111- {
112- case TypeString:
113- case TypeMatch:
114- case TypeColor:
115- variantType = g_strdup ("s");
116- break;
117- case TypeBool:
118- variantType = g_strdup ("b");
119- break;
120- case TypeInt:
121- variantType = g_strdup ("i");
122- break;
123- case TypeFloat:
124- variantType = g_strdup ("d");
125- break;
126- default:
127- variantType = NULL;
128- break;
129- }
130+ hasVariantType = compizconfigTypeHasVariantType (setting->info.forList.listType);
131
132- if (!variantType)
133+ if (!hasVariantType)
134 return FALSE;
135
136 value = g_settings_get_value (settings, cleanSettingName);
137@@ -316,8 +328,8 @@
138 return TRUE;
139 }
140
141- iter = g_variant_iter_new (value);
142- nItems = g_variant_iter_n_children (iter);
143+ g_variant_iter_init (&iter, value);
144+ nItems = g_variant_iter_n_children (&iter);
145
146 switch (setting->info.forList.listType)
147 {
148@@ -325,14 +337,14 @@
149 {
150 Bool *array = malloc (nItems * sizeof (Bool));
151 Bool *arrayCounter = array;
152+ gboolean value;
153
154 if (!array)
155 break;
156-
157- /* Reads each item from the variant into the position pointed
158- * at by arrayCounter */
159- while (g_variant_iter_loop (iter, variantType, arrayCounter))
160- arrayCounter++;
161+
162+ /* Reads each item from the variant into arrayCounter */
163+ while (g_variant_iter_loop (&iter, "b", &value))
164+ *arrayCounter++ = value;
165
166 list = ccsGetValueListFromBoolArray (array, nItems, setting);
167 free (array);
168@@ -342,14 +354,14 @@
169 {
170 int *array = malloc (nItems * sizeof (int));
171 int *arrayCounter = array;
172+ gint value;
173
174 if (!array)
175 break;
176-
177- /* Reads each item from the variant into the position pointed
178- * at by arrayCounter */
179- while (g_variant_iter_loop (iter, variantType, arrayCounter))
180- arrayCounter++;
181+
182+ /* Reads each item from the variant into arrayCounter */
183+ while (g_variant_iter_loop (&iter, "i", &value))
184+ *arrayCounter++ = value;
185
186 list = ccsGetValueListFromIntArray (array, nItems, setting);
187 free (array);
188@@ -359,14 +371,14 @@
189 {
190 double *array = malloc (nItems * sizeof (double));
191 double *arrayCounter = array;
192+ gdouble value;
193
194 if (!array)
195 break;
196-
197- /* Reads each item from the variant into the position pointed
198- * at by arrayCounter */
199- while (g_variant_iter_loop (iter, variantType, arrayCounter))
200- arrayCounter++;
201+
202+ /* Reads each item from the variant into arrayCounter */
203+ while (g_variant_iter_loop (&iter, "f", &value))
204+ *arrayCounter++ = value;
205
206 list = ccsGetValueListFromFloatArray ((float *) array, nItems, setting);
207 free (array);
208@@ -375,24 +387,21 @@
209 case TypeString:
210 case TypeMatch:
211 {
212- char **array = calloc (1, (nItems + 1) * sizeof (char *));
213- char **arrayCounter = array;
214+ gchar **array = calloc (1, (nItems + 1) * sizeof (gchar *));
215+ gchar **arrayCounter = array;
216+ gchar *value;
217
218 if (!array)
219- {
220 break;
221- }
222-
223- /* Reads each item from the variant into the position pointed
224- * at by arrayCounter */
225- while (g_variant_iter_loop (iter, variantType, arrayCounter))
226- arrayCounter++;
227+
228+ array[nItems] = NULL;
229+
230+ /* Reads each item from the variant into arrayCounter */
231+ while (g_variant_iter_next (&iter, "s", &value))
232+ *arrayCounter++ = value;
233
234 list = ccsGetValueListFromStringArray (array, nItems, setting);
235- for (i = 0; i < nItems; i++)
236- if (array[i])
237- free (array[i]);
238- free (array);
239+ g_free (array);
240 }
241 break;
242 case TypeColor:
243@@ -403,7 +412,7 @@
244 if (!array)
245 break;
246
247- while (g_variant_iter_loop (iter, variantType, &colorValue))
248+ while (g_variant_iter_loop (&iter, "s", &colorValue))
249 {
250 memset (&array[i], 0, sizeof (CCSSettingColorValue));
251 ccsStringToColor (colorValue,
252@@ -418,7 +427,6 @@
253 }
254
255 free (cleanSettingName);
256- free (variantType);
257
258 if (list)
259 {
260@@ -639,8 +647,7 @@
261 char *pathName)
262 {
263 GSettings *settings = getSettingsObjectForCCSSetting (setting);
264- GVariant *value;
265- gchar *variantType = NULL;
266+ GVariant *value = NULL;
267 CCSSettingValueList list;
268
269 char *cleanSettingName = translateKeyForGSettings (setting->name);
270@@ -652,7 +659,6 @@
271 {
272 case TypeBool:
273 {
274- variantType = "ab";
275 GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("ab"));
276 while (list)
277 {
278@@ -665,7 +671,6 @@
279 break;
280 case TypeInt:
281 {
282- variantType = "ai";
283 GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("ai"));
284 while (list)
285 {
286@@ -678,7 +683,6 @@
287 break;
288 case TypeFloat:
289 {
290- variantType = "ad";
291 GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("ad"));
292 while (list)
293 {
294@@ -691,7 +695,6 @@
295 break;
296 case TypeString:
297 {
298- variantType = "as";
299 GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
300 while (list)
301 {
302@@ -704,7 +707,6 @@
303 break;
304 case TypeMatch:
305 {
306- variantType = "as";
307 GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
308 while (list)
309 {
310@@ -717,7 +719,6 @@
311 break;
312 case TypeColor:
313 {
314- variantType = "as";
315 GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
316 char *item;
317 while (list)
318@@ -733,11 +734,10 @@
319 default:
320 printf("GSettings backend: attempt to write unsupported list type %d!\n",
321 setting->info.forList.listType);
322- variantType = NULL;
323 break;
324 }
325
326- if (variantType != NULL)
327+ if (value)
328 {
329 g_settings_set_value (settings, cleanSettingName, value);
330 g_variant_unref (value);
331@@ -920,15 +920,15 @@
332 char *currentProfilePath;
333 GVariant *newProfiles;
334 GVariantBuilder *newProfilesBuilder;
335- GVariantIter *iter;
336+ GVariantIter iter;
337 gboolean found = FALSE;
338
339 profiles = g_settings_get_value (compizconfigSettings, "existing-profiles");
340
341 newProfilesBuilder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
342
343- iter = g_variant_iter_new (profiles);
344- while (g_variant_iter_loop (iter, "s", &prof))
345+ g_variant_iter_init (&iter, profiles);
346+ while (g_variant_iter_loop (&iter, "s", &prof))
347 {
348 g_variant_builder_add (newProfilesBuilder, "s", prof);
349
350@@ -942,7 +942,6 @@
351 newProfiles = g_variant_new ("as", newProfilesBuilder);
352 g_settings_set_value (compizconfigSettings, "existing-profiles", newProfiles);
353
354- g_variant_iter_free (iter);
355 g_variant_unref (newProfiles);
356 g_variant_builder_unref (newProfilesBuilder);
357
358@@ -1156,15 +1155,15 @@
359 GVariant *newProfiles;
360 GVariantBuilder *newProfilesBuilder;
361 char *plugin, *prof;
362- GVariantIter *iter;
363+ GVariantIter iter;
364 char *profileSettingsPath = g_strconcat (PROFILEPATH, profile, "/", NULL);
365 GSettings *profileSettings = g_settings_new_with_path (PROFILE_SCHEMA_ID, profileSettingsPath);
366
367 plugins = g_settings_get_value (currentProfileSettings, "plugins-with-set-keys");
368 profiles = g_settings_get_value (compizconfigSettings, "existing-profiles");
369
370- iter = g_variant_iter_new (plugins);
371- while (g_variant_iter_loop (iter, "s", &plugin))
372+ g_variant_iter_init (&iter, plugins);
373+ while (g_variant_iter_loop (&iter, "s", &plugin))
374 {
375 GSettings *settings;
376
377@@ -1190,13 +1189,12 @@
378 }
379
380 /* Remove the profile from existing-profiles */
381- g_variant_iter_free (iter);
382 g_settings_reset (profileSettings, "plugins-with-set-values");
383
384- iter = g_variant_iter_new (profiles);
385+ g_variant_iter_init (&iter, profiles);
386 newProfilesBuilder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
387
388- while (g_variant_iter_loop (iter, "s", &prof))
389+ while (g_variant_iter_loop (&iter, "s", &prof))
390 {
391 if (g_strcmp0 (prof, profile))
392 g_variant_builder_add (newProfilesBuilder, "s", prof);

Subscribers

People subscribed via source and target branches