[libgweather/wip/hadess/serialisation-fix: 1/17] GWeatherLocation: Fix double-free with "nearest stations"



commit b2a1468accc3ead062eb4c0c48deaa5a5ab792c7
Author: Bastien Nocera <hadess hadess net>
Date:   Tue Oct 9 14:39:08 2018 +0200

    GWeatherLocation: Fix double-free with "nearest stations"
    
    The nearest station code would try to (badly) copy the nearest station's
    location to add it as a child, but the copy was shallow, and the string
    pointers, and other allocated memory wasn't duplicated, leading to
    double-frees and invalid memory accesses if the world was unref'ed.
    
    This also fixes the newly created GWeatherLocation to use g_slice_* to
    allocate the memory chunk, otherwise we'll have memory corruption when
    we try to free it with g_slice_free() in the unref() code.

 libgweather/gweather-location.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)
---
diff --git a/libgweather/gweather-location.c b/libgweather/gweather-location.c
index d122e0e..976b8b9 100644
--- a/libgweather/gweather-location.c
+++ b/libgweather/gweather-location.c
@@ -136,12 +136,15 @@ location_new (GWeatherLocationLevel level)
     return loc;
 }
 
+static void add_timezones (GWeatherLocation *loc, GPtrArray *zones);
+
 static void
 add_nearest_weather_station (GWeatherLocation *location)
 {
-    GWeatherLocation **siblings;
+    GWeatherLocation **siblings, *station;
     GWeatherLocation *closest = NULL;
     double min_distance = G_MAXDOUBLE;
+    GPtrArray *zones;
     guint i;
 
     g_assert (location->parent);
@@ -172,7 +175,30 @@ add_nearest_weather_station (GWeatherLocation *location)
     }
 
     location->children = g_new0 (GWeatherLocation *, 2);
-    location->children[0] = g_memdup (closest, sizeof(GWeatherLocation));
+    location->children[0] = g_slice_new0 (GWeatherLocation);
+    station = location->children[0];
+    station->english_name = g_strdup (closest->english_name);
+    station->local_name = g_strdup (closest->local_name);
+    station->msgctxt = g_strdup (closest->msgctxt);
+    station->local_sort_name = g_strdup (closest->local_sort_name);
+    station->english_sort_name = g_strdup (closest->english_sort_name);
+    station->parent = location;
+    station->level = closest->level;
+    station->country_code = g_strdup (closest->country_code);
+    station->tz_hint = g_strdup (closest->tz_hint);
+    station->station_code = g_strdup (closest->station_code);
+    station->forecast_zone = g_strdup (closest->forecast_zone);
+    station->radar = g_strdup (closest->radar);
+    station->latitude = closest->latitude;
+    station->longitude = closest->longitude;
+    station->latlon_valid = closest->latlon_valid;
+
+    zones = g_ptr_array_new ();
+    add_timezones (station, zones);
+    g_ptr_array_add (zones, NULL);
+    station->zones = (GWeatherTimezone **)g_ptr_array_free (zones, FALSE);
+
+    station->ref_count = 1;
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]