Merge lp:~compiz-team/compiz/compiz.fix_1018602 into lp:compiz/0.9.8
- compiz.fix_1018602
- Merge into 0.9.8
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 |
Related bugs: |
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.
Commit message
Description of the change
Fixes LP (#1018602) : An invalid read when using g_variant_
No tests yet, tests will be added to gsettings in another commit when the lcc testing work lands.
Daniel van Vugt (vanvugt) : Posted in a previous version of this proposal | # |
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
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
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
Daniel van Vugt (vanvugt) wrote : | # |
The addition of compizconfigTyp
We already have a tight coupling between:
TYPE x;
and:
g_variant_
Using:
g_variant_
only makes the code harder to read, with looser coupling and weaker cohesion.
Please remove compizconfigTyp
g_variant_
Daniel van Vugt (vanvugt) wrote : | # |
It's the same as:
printf(
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);
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.
Daniel van Vugt (vanvugt) wrote : | # |
Maybe. But back to the actual case of g_variant_
int v;
g_variant_
- 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
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); |
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: iter_next (iter, "s", &value))
while (g_variant_
*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.