Merge lp:~compiz-team/compiz/compiz.fix_1018602 into lp:compiz/0.9.8
- compiz.fix_1018602
- Merge into 0.9.8
Status: | Merged |
---|---|
Merged at revision: | 3267 |
Proposed branch: | lp:~compiz-team/compiz/compiz.fix_1018602 |
Merge into: | lp:compiz/0.9.8 |
Diff against target: |
497 lines (+120/-96) 1 file modified
compizconfig/gsettings/src/gsettings.c (+120/-96) |
To merge this branch: | bzr merge lp:~compiz-team/compiz/compiz.fix_1018602 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel van Vugt | Approve | ||
Review via email: mp+112718@code.launchpad.net |
This proposal supersedes 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 : Posted in a previous version of this proposal | # |
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 : Posted in a previous version of this proposal | # |
Thanks for the tip on using g_variant_iter_next ... that's now fixed too.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
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 : Posted in a previous version of this proposal | # |
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 : Posted in a previous version of this proposal | # |
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 : Posted in a previous version of this proposal | # |
Maybe. But back to the actual case of g_variant_
int v;
g_variant_
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
I had another look at the code and variantType is more or less used as a placeholder so that copypasting was easier and so that we could return if there was no variant type for that setting. The fact that we are copypasting is a problem, but I modified the function so that it returns a boolean for whether or not we can read that type of setting.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
It works OK, but I can see some potentially serious mistakes:
203: "f" should be "d"
(http://
235: Missing g_free() loop:
for (i = 0; i < nItems; i++)
if (array[i])
239: g_free() on calloc'd block (214). Either change g_free() to free(), or calloc() to g_malloc0().
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
> It works OK, but I can see some potentially serious mistakes:
>
> 203: "f" should be "d"
> (http://
Thanks, fixed.
>
> 235: Missing g_free() loop:
> for (i = 0; i < nItems; i++)
> if (array[i])
> g_free(array[i]);
My understanding is that g_variant_iter_next returns a shallow copy of the array, so free () is sufficient in this case (unlike the previous code where we copied the values out of the array. Valgrind reports there are no leaks here.
>
> 239: g_free() on calloc'd block (214). Either change g_free() to free(), or
> calloc() to g_malloc0().
Fixed, although I think g_malloc is a wrapper around malloc itself (eg, doesn't use g_slice_alloc)
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
No, you still need the g_free loop to free each array element after g_variant_
http://
It's possible valgrind doesn't see the leak because the memory is managed by glib and freed at exit. But it's still a leak even still.
Also, I was referring to g_malloc0() to replace calloc. Not g_malloc(). :)
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
You're right, I was confusing the array with the values themselves. Fixing it now.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Still needs fixing. Please don't click resubmit till after you've pushed the changes.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Sorry, my fault. I commented on an old version of the proposal. But still needs fixing.
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
Fixed that, plugged other memleaks.
Daniel van Vugt (vanvugt) wrote : | # |
Thanks for the extra leak fixes but they're not part of fixing the crash.
I give up. It looks OK now but I don't want to manually test and valgrind it again. We'll be valgrinding a lot more in the near future.
Preview Diff
1 | === modified file 'compizconfig/gsettings/src/gsettings.c' |
2 | --- compizconfig/gsettings/src/gsettings.c 2012-06-28 09:03:09 +0000 |
3 | +++ compizconfig/gsettings/src/gsettings.c 2012-06-29 07:54:24 +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 | @@ -121,10 +146,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 | @@ -143,6 +169,8 @@ |
52 | return settingsObj; |
53 | } |
54 | |
55 | + g_free (name); |
56 | + |
57 | l = g_list_next (l); |
58 | } |
59 | |
60 | @@ -162,26 +190,31 @@ |
61 | |
62 | writtenPlugins = g_settings_get_value (currentProfileSettings, "plugins-with-set-keys"); |
63 | |
64 | - newWrittenPluginsBuilder = g_variant_builder_new (G_VARIANT_TYPE ("as")); |
65 | + g_variant_iter_init (&iter, writtenPlugins); |
66 | + newWrittenPluginsSize = g_variant_iter_n_children (&iter); |
67 | |
68 | - iter = g_variant_iter_new (writtenPlugins); |
69 | - while (g_variant_iter_loop (iter, "s", &plug)) |
70 | + while (g_variant_iter_loop (&iter, "s", &plug)) |
71 | { |
72 | - g_variant_builder_add (newWrittenPluginsBuilder, "s", plug); |
73 | - |
74 | if (!found) |
75 | found = (g_strcmp0 (plug, plugin) == 0); |
76 | } |
77 | |
78 | if (!found) |
79 | - g_variant_builder_add (newWrittenPluginsBuilder, "s", plugin); |
80 | - |
81 | - newWrittenPlugins = g_variant_new ("as", newWrittenPluginsBuilder); |
82 | - g_settings_set_value (currentProfileSettings, "plugins-with-set-keys", newWrittenPlugins); |
83 | - |
84 | - g_variant_iter_free (iter); |
85 | - g_variant_unref (newWrittenPlugins); |
86 | - g_variant_builder_unref (newWrittenPluginsBuilder); |
87 | + newWrittenPluginsSize++; |
88 | + |
89 | + newWrittenPlugins = g_variant_dup_strv (writtenPlugins, &writtenPluginsLen); |
90 | + |
91 | + if (writtenPluginsLen > newWrittenPluginsSize) |
92 | + { |
93 | + newWrittenPlugins = g_realloc (newWrittenPlugins, (newWrittenPluginsSize + 1) * sizeof (gchar *)); |
94 | + newWrittenPlugins[writtenPluginsLen + 1] = g_strdup (plugin); |
95 | + newWrittenPlugins[newWrittenPluginsSize] = NULL; |
96 | + } |
97 | + |
98 | + g_settings_set_strv (currentProfileSettings, "plugins-with-set-keys", (const gchar * const *)newWrittenPlugins); |
99 | + |
100 | + g_free (schemaName); |
101 | + g_strfreev (newWrittenPlugins); |
102 | |
103 | return settingsObj; |
104 | } |
105 | @@ -213,36 +246,52 @@ |
106 | { |
107 | CCSContext *context = (CCSContext *)user_data; |
108 | char *uncleanKeyName; |
109 | - char *path; |
110 | + char *path, *pathOrig; |
111 | char *token; |
112 | int index; |
113 | unsigned int screenNum; |
114 | CCSPlugin *plugin; |
115 | CCSSetting *setting; |
116 | |
117 | - g_object_get (G_OBJECT (settings), "path", &path, NULL); |
118 | + g_object_get (G_OBJECT (settings), "path", &pathOrig, NULL); |
119 | |
120 | + path = pathOrig; |
121 | path += strlen (COMPIZ) + 1; |
122 | |
123 | token = strsep (&path, "/"); /* Profile name */ |
124 | if (!token) |
125 | + { |
126 | + g_free (pathOrig); |
127 | return; |
128 | + } |
129 | |
130 | token = strsep (&path, "/"); /* plugins */ |
131 | if (!token) |
132 | + { |
133 | + g_free (pathOrig); |
134 | return; |
135 | + } |
136 | |
137 | token = strsep (&path, "/"); /* plugin */ |
138 | if (!token) |
139 | + { |
140 | + g_free (pathOrig); |
141 | return; |
142 | + } |
143 | |
144 | plugin = ccsFindPlugin (context, token); |
145 | if (!plugin) |
146 | + { |
147 | + g_free (pathOrig); |
148 | return; |
149 | + } |
150 | |
151 | token = strsep (&path, "/"); /* screen%i */ |
152 | if (!token) |
153 | + { |
154 | + g_free (pathOrig); |
155 | return; |
156 | + } |
157 | |
158 | sscanf (token, "screen%d", &screenNum); |
159 | |
160 | @@ -253,6 +302,7 @@ |
161 | { |
162 | printf ("GSettings Backend: unable to find setting %s, for path %s\n", uncleanKeyName, path); |
163 | free (uncleanKeyName); |
164 | + g_free (pathOrig); |
165 | return; |
166 | } |
167 | |
168 | @@ -270,42 +320,24 @@ |
169 | } |
170 | |
171 | free (uncleanKeyName); |
172 | + g_free (pathOrig); |
173 | } |
174 | |
175 | static Bool |
176 | readListValue (CCSSetting *setting) |
177 | { |
178 | GSettings *settings = getSettingsObjectForCCSSetting (setting); |
179 | - gchar *variantType; |
180 | + gboolean hasVariantType; |
181 | unsigned int nItems, i = 0; |
182 | CCSSettingValueList list = NULL; |
183 | GVariant *value; |
184 | - GVariantIter *iter; |
185 | + GVariantIter iter; |
186 | |
187 | char *cleanSettingName = translateKeyForGSettings (setting->name); |
188 | |
189 | - switch (setting->info.forList.listType) |
190 | - { |
191 | - case TypeString: |
192 | - case TypeMatch: |
193 | - case TypeColor: |
194 | - variantType = g_strdup ("s"); |
195 | - break; |
196 | - case TypeBool: |
197 | - variantType = g_strdup ("b"); |
198 | - break; |
199 | - case TypeInt: |
200 | - variantType = g_strdup ("i"); |
201 | - break; |
202 | - case TypeFloat: |
203 | - variantType = g_strdup ("d"); |
204 | - break; |
205 | - default: |
206 | - variantType = NULL; |
207 | - break; |
208 | - } |
209 | + hasVariantType = compizconfigTypeHasVariantType (setting->info.forList.listType); |
210 | |
211 | - if (!variantType) |
212 | + if (!hasVariantType) |
213 | return FALSE; |
214 | |
215 | value = g_settings_get_value (settings, cleanSettingName); |
216 | @@ -315,8 +347,8 @@ |
217 | return TRUE; |
218 | } |
219 | |
220 | - iter = g_variant_iter_new (value); |
221 | - nItems = g_variant_iter_n_children (iter); |
222 | + g_variant_iter_init (&iter, value); |
223 | + nItems = g_variant_iter_n_children (&iter); |
224 | |
225 | switch (setting->info.forList.listType) |
226 | { |
227 | @@ -324,14 +356,14 @@ |
228 | { |
229 | Bool *array = malloc (nItems * sizeof (Bool)); |
230 | Bool *arrayCounter = array; |
231 | + gboolean value; |
232 | |
233 | if (!array) |
234 | break; |
235 | - |
236 | - /* Reads each item from the variant into the position pointed |
237 | - * at by arrayCounter */ |
238 | - while (g_variant_iter_loop (iter, variantType, arrayCounter)) |
239 | - arrayCounter++; |
240 | + |
241 | + /* Reads each item from the variant into arrayCounter */ |
242 | + while (g_variant_iter_loop (&iter, "b", &value)) |
243 | + *arrayCounter++ = value; |
244 | |
245 | list = ccsGetValueListFromBoolArray (array, nItems, setting); |
246 | free (array); |
247 | @@ -341,14 +373,14 @@ |
248 | { |
249 | int *array = malloc (nItems * sizeof (int)); |
250 | int *arrayCounter = array; |
251 | + gint value; |
252 | |
253 | if (!array) |
254 | break; |
255 | - |
256 | - /* Reads each item from the variant into the position pointed |
257 | - * at by arrayCounter */ |
258 | - while (g_variant_iter_loop (iter, variantType, arrayCounter)) |
259 | - arrayCounter++; |
260 | + |
261 | + /* Reads each item from the variant into arrayCounter */ |
262 | + while (g_variant_iter_loop (&iter, "i", &value)) |
263 | + *arrayCounter++ = value; |
264 | |
265 | list = ccsGetValueListFromIntArray (array, nItems, setting); |
266 | free (array); |
267 | @@ -358,14 +390,14 @@ |
268 | { |
269 | double *array = malloc (nItems * sizeof (double)); |
270 | double *arrayCounter = array; |
271 | + gdouble value; |
272 | |
273 | if (!array) |
274 | break; |
275 | - |
276 | - /* Reads each item from the variant into the position pointed |
277 | - * at by arrayCounter */ |
278 | - while (g_variant_iter_loop (iter, variantType, arrayCounter)) |
279 | - arrayCounter++; |
280 | + |
281 | + /* Reads each item from the variant into arrayCounter */ |
282 | + while (g_variant_iter_loop (&iter, "d", &value)) |
283 | + *arrayCounter++ = value; |
284 | |
285 | list = ccsGetValueListFromFloatArray ((float *) array, nItems, setting); |
286 | free (array); |
287 | @@ -374,24 +406,21 @@ |
288 | case TypeString: |
289 | case TypeMatch: |
290 | { |
291 | - char **array = calloc (1, (nItems + 1) * sizeof (char *)); |
292 | - char **arrayCounter = array; |
293 | + gchar **array = g_malloc0 ((nItems + 1) * sizeof (gchar *)); |
294 | + gchar **arrayCounter = array; |
295 | + gchar *value; |
296 | |
297 | if (!array) |
298 | - { |
299 | break; |
300 | - } |
301 | - |
302 | - /* Reads each item from the variant into the position pointed |
303 | - * at by arrayCounter */ |
304 | - while (g_variant_iter_loop (iter, variantType, arrayCounter)) |
305 | - arrayCounter++; |
306 | + |
307 | + array[nItems] = NULL; |
308 | + |
309 | + /* Reads each item from the variant into arrayCounter */ |
310 | + while (g_variant_iter_next (&iter, "s", &value)) |
311 | + *arrayCounter++ = value; |
312 | |
313 | list = ccsGetValueListFromStringArray (array, nItems, setting); |
314 | - for (i = 0; i < nItems; i++) |
315 | - if (array[i]) |
316 | - free (array[i]); |
317 | - free (array); |
318 | + g_strfreev (array); |
319 | } |
320 | break; |
321 | case TypeColor: |
322 | @@ -402,7 +431,7 @@ |
323 | if (!array) |
324 | break; |
325 | |
326 | - while (g_variant_iter_loop (iter, variantType, &colorValue)) |
327 | + while (g_variant_iter_loop (&iter, "s", &colorValue)) |
328 | { |
329 | memset (&array[i], 0, sizeof (CCSSettingColorValue)); |
330 | ccsStringToColor (colorValue, |
331 | @@ -417,7 +446,6 @@ |
332 | } |
333 | |
334 | free (cleanSettingName); |
335 | - free (variantType); |
336 | |
337 | if (list) |
338 | { |
339 | @@ -638,8 +666,7 @@ |
340 | char *pathName) |
341 | { |
342 | GSettings *settings = getSettingsObjectForCCSSetting (setting); |
343 | - GVariant *value; |
344 | - gchar *variantType = NULL; |
345 | + GVariant *value = NULL; |
346 | CCSSettingValueList list; |
347 | |
348 | char *cleanSettingName = translateKeyForGSettings (setting->name); |
349 | @@ -651,7 +678,6 @@ |
350 | { |
351 | case TypeBool: |
352 | { |
353 | - variantType = "ab"; |
354 | GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("ab")); |
355 | while (list) |
356 | { |
357 | @@ -664,7 +690,6 @@ |
358 | break; |
359 | case TypeInt: |
360 | { |
361 | - variantType = "ai"; |
362 | GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("ai")); |
363 | while (list) |
364 | { |
365 | @@ -677,7 +702,6 @@ |
366 | break; |
367 | case TypeFloat: |
368 | { |
369 | - variantType = "ad"; |
370 | GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("ad")); |
371 | while (list) |
372 | { |
373 | @@ -690,7 +714,6 @@ |
374 | break; |
375 | case TypeString: |
376 | { |
377 | - variantType = "as"; |
378 | GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); |
379 | while (list) |
380 | { |
381 | @@ -703,7 +726,6 @@ |
382 | break; |
383 | case TypeMatch: |
384 | { |
385 | - variantType = "as"; |
386 | GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); |
387 | while (list) |
388 | { |
389 | @@ -716,7 +738,6 @@ |
390 | break; |
391 | case TypeColor: |
392 | { |
393 | - variantType = "as"; |
394 | GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("as")); |
395 | char *item; |
396 | while (list) |
397 | @@ -732,11 +753,10 @@ |
398 | default: |
399 | printf("GSettings backend: attempt to write unsupported list type %d!\n", |
400 | setting->info.forList.listType); |
401 | - variantType = NULL; |
402 | break; |
403 | } |
404 | |
405 | - if (variantType != NULL) |
406 | + if (value) |
407 | { |
408 | g_settings_set_value (settings, cleanSettingName, value); |
409 | g_variant_unref (value); |
410 | @@ -911,7 +931,7 @@ |
411 | } |
412 | |
413 | static void |
414 | -updateCurrentProfileName (char *profile) |
415 | +updateCurrentProfileName (const char *profile) |
416 | { |
417 | GVariant *profiles; |
418 | char *prof; |
419 | @@ -919,15 +939,15 @@ |
420 | char *currentProfilePath; |
421 | GVariant *newProfiles; |
422 | GVariantBuilder *newProfilesBuilder; |
423 | - GVariantIter *iter; |
424 | + GVariantIter iter; |
425 | gboolean found = FALSE; |
426 | |
427 | profiles = g_settings_get_value (compizconfigSettings, "existing-profiles"); |
428 | |
429 | newProfilesBuilder = g_variant_builder_new (G_VARIANT_TYPE ("as")); |
430 | |
431 | - iter = g_variant_iter_new (profiles); |
432 | - while (g_variant_iter_loop (iter, "s", &prof)) |
433 | + g_variant_iter_init (&iter, profiles); |
434 | + while (g_variant_iter_loop (&iter, "s", &prof)) |
435 | { |
436 | g_variant_builder_add (newProfilesBuilder, "s", prof); |
437 | |
438 | @@ -941,7 +961,6 @@ |
439 | newProfiles = g_variant_new ("as", newProfilesBuilder); |
440 | g_settings_set_value (compizconfigSettings, "existing-profiles", newProfiles); |
441 | |
442 | - g_variant_iter_free (iter); |
443 | g_variant_unref (newProfiles); |
444 | g_variant_builder_unref (newProfilesBuilder); |
445 | |
446 | @@ -962,8 +981,14 @@ |
447 | { |
448 | char *profile = strdup (ccsGetProfile (context)); |
449 | |
450 | - if (!profile || !strlen (profile)) |
451 | - profile = strdup (DEFAULTPROF); |
452 | + if (!profile) |
453 | + profile = strdup (DEFAULTPROF); |
454 | + |
455 | + if (!strlen (profile)) |
456 | + { |
457 | + free (profile); |
458 | + profile = strdup (DEFAULTPROF); |
459 | + } |
460 | |
461 | if (g_strcmp0 (profile, currentProfile)) |
462 | updateCurrentProfileName (profile); |
463 | @@ -1155,15 +1180,15 @@ |
464 | GVariant *newProfiles; |
465 | GVariantBuilder *newProfilesBuilder; |
466 | char *plugin, *prof; |
467 | - GVariantIter *iter; |
468 | + GVariantIter iter; |
469 | char *profileSettingsPath = g_strconcat (PROFILEPATH, profile, "/", NULL); |
470 | GSettings *profileSettings = g_settings_new_with_path (PROFILE_SCHEMA_ID, profileSettingsPath); |
471 | |
472 | plugins = g_settings_get_value (currentProfileSettings, "plugins-with-set-keys"); |
473 | profiles = g_settings_get_value (compizconfigSettings, "existing-profiles"); |
474 | |
475 | - iter = g_variant_iter_new (plugins); |
476 | - while (g_variant_iter_loop (iter, "s", &plugin)) |
477 | + g_variant_iter_init (&iter, plugins); |
478 | + while (g_variant_iter_loop (&iter, "s", &plugin)) |
479 | { |
480 | GSettings *settings; |
481 | |
482 | @@ -1189,13 +1214,12 @@ |
483 | } |
484 | |
485 | /* Remove the profile from existing-profiles */ |
486 | - g_variant_iter_free (iter); |
487 | g_settings_reset (profileSettings, "plugins-with-set-values"); |
488 | |
489 | - iter = g_variant_iter_new (profiles); |
490 | + g_variant_iter_init (&iter, profiles); |
491 | newProfilesBuilder = g_variant_builder_new (G_VARIANT_TYPE ("as")); |
492 | |
493 | - while (g_variant_iter_loop (iter, "s", &prof)) |
494 | + while (g_variant_iter_loop (&iter, "s", &prof)) |
495 | { |
496 | if (g_strcmp0 (prof, profile)) |
497 | 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.