Merge lp:~dshea/timezonemap/memory-problems into lp:timezonemap

Proposed by David Shea
Status: Needs review
Proposed branch: lp:~dshea/timezonemap/memory-problems
Merge into: lp:timezonemap
Diff against target: 155 lines (+47/-20)
3 files modified
debian/control (+2/-2)
src/cc-timezone-map.c (+35/-4)
src/tz.c (+10/-14)
To merge this branch: bzr merge lp:~dshea/timezonemap/memory-problems
Reviewer Review Type Date Requested Status
Timezone Map Team Pending
Review via email: mp+295635@code.launchpad.net

Description of the change

This fixes a memory leak and an access of freed memory, and works around a call to setenv which is not thread-safe. tz_location_set_locally could probably be removed but it's kind of part of the public interface so I didn't want to mess with that.

To post a comment you must log in.
62. By David Shea

Fix the calculation of time zone offsets.

g_get_real_time returns microseconds, not milliseconds.

Unmerged revisions

62. By David Shea

Fix the calculation of time zone offsets.

g_get_real_time returns microseconds, not milliseconds.

61. By David Shea

Do not use tz_location_get_utc_offset

The function in tz.c to fetch the timezone offset for a given location
sets the TZ environment variable which, besides being potentially
surprising to the rest of the process, is not thread-safe. Instead,
skip the function entirely and use the glib functions for querying time
zone data.

Increase the required glib version to 2.26 for the GTimeZone functions.

60. By David Shea

Fix an invalid memory access

When truncating the list for the distance-based location search, do not
attempt to read the rest of the list after it has been freed.

59. By David Shea

Fix memory leaks in tz.c

Use a stack-allocated block for the user_data struct passed to
parse_cities15000, since the struct itself is not needed after
parse_file, and no one can forget to free it if it's not dynamically
allocated the first place.

Use const strings in tz_data_file_get so that the return value does not
need to be duplicated and freed.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2015-05-07 13:47:16 +0000
3+++ debian/control 2016-06-28 17:25:08 +0000
4@@ -9,7 +9,7 @@
5 gir1.2-glib-2.0,
6 gir1.2-gtk-3.0,
7 intltool (>= 0.35.0),
8- libglib2.0-dev (>= 2.25.0),
9+ libglib2.0-dev (>= 2.26.0),
10 libgtk-3-dev (>= 3.1.4),
11 libcairo2-dev (>= 1.10),
12 libjson-glib-dev,
13@@ -57,7 +57,7 @@
14 Depends: ${shlibs:Depends},
15 ${misc:Depends},
16 libtimezonemap1 (= ${binary:Version}),
17- libglib2.0-dev (>= 2.25.0),
18+ libglib2.0-dev (>= 2.26.0),
19 libgtk-3-dev (>= 3.1.4),
20 libjson-glib-dev
21 Replaces: gir1.2-timezonemap-1.0 (<< 0.3)
22
23=== modified file 'src/cc-timezone-map.c'
24--- src/cc-timezone-map.c 2015-05-07 16:43:32 +0000
25+++ src/cc-timezone-map.c 2016-06-28 17:25:08 +0000
26@@ -843,6 +843,39 @@
27 return 0;
28 }
29
30+/* Return the UTC offset (in hours) for the standard (winter) time at a location */
31+static gdouble
32+get_location_offset (CcTimezoneLocation *location)
33+{
34+ const gchar *zone_name;
35+ GTimeZone *zone;
36+ gint interval;
37+ gint64 curtime;
38+ gint32 offset;
39+
40+ g_return_val_if_fail (location != NULL, 0);
41+ zone_name = cc_timezone_location_get_zone (location);
42+ g_return_val_if_fail (zone_name != NULL, 0);
43+
44+ zone = g_time_zone_new (zone_name);
45+
46+ /* Query the zone based on the current time, since otherwise the data
47+ * may not make sense. */
48+ curtime = g_get_real_time () / 1000000; /* convert to seconds */
49+ interval = g_time_zone_find_interval (zone, G_TIME_TYPE_UNIVERSAL, curtime);
50+
51+ offset = g_time_zone_get_offset (zone, interval);
52+ if (g_time_zone_is_dst (zone, interval))
53+ {
54+ /* Subtract an hour's worth of seconds to get the standard time offset */
55+ offset -= (60 * 60);
56+ }
57+
58+ g_time_zone_unref (zone);
59+
60+ return offset / (60.0 * 60.0);
61+}
62+
63 static void
64 set_location (CcTimezoneMap *map,
65 CcTimezoneLocation *location)
66@@ -854,11 +887,8 @@
67
68 if (priv->location)
69 {
70- info = tz_info_from_location (priv->location);
71- priv->selected_offset = tz_location_get_utc_offset (priv->location)
72- / (60.0*60.0) + ((info->daylight) ? -1.0 : 0.0);
73+ priv->selected_offset = get_location_offset (priv->location);
74 priv->show_offset = TRUE;
75- tz_info_free (info);
76 }
77 else
78 {
79@@ -940,6 +970,7 @@
80 /* Cut the list off here */
81 node->prev->next = NULL;
82 g_list_free(node);
83+ break;
84 }
85
86 node = g_list_next(node);
87
88=== modified file 'src/tz.c'
89--- src/tz.c 2013-12-16 17:01:37 +0000
90+++ src/tz.c 2016-06-28 17:25:08 +0000
91@@ -41,7 +41,7 @@
92 #endif
93 static int compare_country_names (const void *a, const void *b);
94 static void sort_locations_by_country (GPtrArray *locations);
95-static gchar * tz_data_file_get (gchar *env, gchar *defaultfile);
96+static const gchar * tz_data_file_get (const gchar *env, const gchar *defaultfile);
97
98 void parse_file (const char * filename,
99 const guint ncolumns,
100@@ -179,7 +179,7 @@
101 TzDB *
102 tz_load_db (void)
103 {
104- gchar *tz_data_file, *admin1_file, *country_file;
105+ const gchar *tz_data_file, *admin1_file, *country_file;
106 TzDB *tz_db;
107 char buf[4096];
108
109@@ -217,23 +217,19 @@
110 tz_db = g_new0 (TzDB, 1);
111 tz_db->locations = g_ptr_array_new ();
112
113- Triple * triple = g_new (Triple, 1);
114- triple->first = tz_db->locations;
115- triple->second = stateHash;
116- triple->third = countryHash;
117+ Triple triple;
118+ triple.first = tz_db->locations;
119+ triple.second = stateHash;
120+ triple.third = countryHash;
121
122- parse_file (tz_data_file, 19, parse_cities15000, triple);
123+ parse_file (tz_data_file, 19, parse_cities15000, &triple);
124
125 g_hash_table_destroy (stateHash);
126 g_hash_table_destroy (countryHash);
127- triple->second = NULL;
128- triple->third = NULL;
129
130 /* now sort by country */
131 sort_locations_by_country (tz_db->locations);
132
133- g_free (tz_data_file);
134-
135 return tz_db;
136 }
137
138@@ -391,14 +387,14 @@
139 * Private functions *
140 * ----------------- */
141
142-static gchar *
143-tz_data_file_get (gchar *env, gchar *defaultfile)
144+static const gchar *
145+tz_data_file_get (const gchar *env, const gchar *defaultfile)
146 {
147 /* Allow passing this in at runtime, to support loading it from the build
148 * tree during tests. */
149 const gchar * filename = g_getenv (env);
150
151- return filename ? g_strdup (filename) : g_strdup (defaultfile);
152+ return filename ? filename : defaultfile;
153 }
154
155 #ifdef __sun

Subscribers

People subscribed via source and target branches

to all changes: