From 108a3f9554f7a6c6f9b60325588981b4111baab0 Mon Sep 17 00:00:00 2001 From: John Ralls <jralls@ceridwen.us> Date: Fri, 23 May 2014 15:18:14 -0700 Subject: [PATCH 2/2] Bug 730332: Guard against reading past the end of a truncated tz file. Read the 32-bit data if the file is long enough. --- glib/gtimezone.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) --- glib-2.41.2/glib/gtimezone.c.orig 2014-07-19 20:11:23.370423979 +0100 +++ glib-2.41.2/glib/gtimezone.c 2014-07-20 12:42:41.037193639 +0100 @@ -439,7 +439,7 @@ static void init_zone_from_iana_info (GTimeZone *gtz, GBytes *zoneinfo) { - gsize size; + gsize size, datasize32, datasize64; guint index; guint32 time_count, type_count; guint8 *tz_transitions, *tz_type_index, *tz_ttinfo; @@ -447,22 +447,32 @@ gsize timesize = sizeof (gint32); const struct tzhead *header = g_bytes_get_data (zoneinfo, &size); - g_return_if_fail (size >= sizeof (struct tzhead) && + datasize32 = guint32_from_be(header->tzh_ttisgmtcnt) + + guint32_from_be(header->tzh_ttisstdcnt) + + sizeof (gint32) * 2 * guint32_from_be(header->tzh_leapcnt) + + (sizeof (gint32) + sizeof (gint8)) * guint32_from_be(header->tzh_timecnt) + + sizeof(struct ttinfo) * guint32_from_be(header->tzh_typecnt) + + guint32_from_be(header->tzh_charcnt); + + datasize64 = guint32_from_be(header->tzh_ttisgmtcnt) + + guint32_from_be(header->tzh_ttisstdcnt) + + sizeof (gint32) * 2 * guint32_from_be(header->tzh_leapcnt) + + (sizeof (gint64) + sizeof (gint8)) * guint32_from_be(header->tzh_timecnt) + + sizeof(struct ttinfo) * guint32_from_be(header->tzh_typecnt) + + guint32_from_be(header->tzh_charcnt); + + g_return_if_fail (size >= (sizeof (struct tzhead) + datasize32) && memcmp (header, "TZif", 4) == 0); - if (header->tzh_version == '2') + if (header->tzh_version == '2' && + size >= (2 * sizeof (struct tzhead) + datasize32 + datasize64)) { /* Skip ahead to the newer 64-bit data if it's available. */ header = (const struct tzhead *) - (((const gchar *) (header + 1)) + - guint32_from_be(header->tzh_ttisgmtcnt) + - guint32_from_be(header->tzh_ttisstdcnt) + - 8 * guint32_from_be(header->tzh_leapcnt) + - 5 * guint32_from_be(header->tzh_timecnt) + - 6 * guint32_from_be(header->tzh_typecnt) + - guint32_from_be(header->tzh_charcnt)); + (((const gchar *) (header + 1)) + datasize32); timesize = sizeof (gint64); } + time_count = guint32_from_be(header->tzh_timecnt); type_count = guint32_from_be(header->tzh_typecnt);