diff options
author | Simon McVittie <smcv@collabora.com> | 2023-05-16 12:15:45 +0100 |
---|---|---|
committer | Simon McVittie <smcv@collabora.com> | 2023-05-17 11:35:44 +0100 |
commit | 35e7e682006898805b2861944226c20430dd3096 (patch) | |
tree | 3f730b626bb81cf6b802f4dac63d895332bf4d25 | |
parent | 9834f8991d24dc5a24d0d9d525497b85ffa22307 (diff) | |
download | flatpak-35e7e682006898805b2861944226c20430dd3096.tar.gz |
glib-backports: Resync ISO8601 parsing with GLib 2.76.2
- 3384ed3f "Fixing signedness warnings in glib/gdatetime.c"
- faa1d63c "glib: Fix various compiler warnings when compiling with G_DISABLE_ASSERT"
- 4ddabfc6 "gdatetime: Avoid an assertion failure when parsing some ISO 8601 dates"
- b4eaac58 "gdatetime: Handle leap seconds in ISO8601 dates"
- f9d0135a "gdatetime: Port to use new g_time_zone_new_identifier() constructor"
(partially reverted here)
- c3805d74 "gdatetime: Disallow NAN as a number of seconds in a GDateTime"
- 5d7f4b8f "gdatetime: Remove floating point from seconds parsing code"
- d5580edf "Fix non-initialized variable in glib/gdatetime.c"
-rw-r--r-- | common/flatpak-glib-backports.c | 58 |
1 files changed, 39 insertions, 19 deletions
diff --git a/common/flatpak-glib-backports.c b/common/flatpak-glib-backports.c index 02236240..c4c30ad1 100644 --- a/common/flatpak-glib-backports.c +++ b/common/flatpak-glib-backports.c @@ -32,7 +32,7 @@ * oldest first. */ #if !GLIB_CHECK_VERSION (2, 56, 0) -/* All this code is backported directly from glib */ +/* All this code is backported directly from GLib 2.76.2 except where noted */ static void g_date_time_get_week_number (GDateTime *datetime, @@ -40,7 +40,7 @@ g_date_time_get_week_number (GDateTime *datetime, gint *day_of_week, gint *day_of_year) { - gint a, b, c, d, e, f, g, n, s, month, day, year; + gint a, b, c, d, e, f, g, n, s, month = -1, day = -1, year = -1; g_date_time_get_ymd (datetime, &year, &month, &day); @@ -90,7 +90,8 @@ g_date_time_get_week_number (GDateTime *datetime, static gboolean get_iso8601_int (const gchar *text, gsize length, gint *value) { - gint i, v = 0; + gsize i; + guint v = 0; if (length < 1 || length > 4) return FALSE; @@ -111,8 +112,8 @@ get_iso8601_int (const gchar *text, gsize length, gint *value) static gboolean get_iso8601_seconds (const gchar *text, gsize length, gdouble *value) { - gint i; - gdouble divisor = 1, v = 0; + gsize i; + guint64 divisor = 1, v = 0; if (length < 2) return FALSE; @@ -127,6 +128,11 @@ get_iso8601_seconds (const gchar *text, gsize length, gdouble *value) if (length > 2 && !(text[i] == '.' || text[i] == ',')) return FALSE; + + /* Ignore leap seconds, see g_date_time_new_from_iso8601() */ + if (v >= 60.0 && v <= 61.0) + v = 59.0; + i++; if (i == length) return FALSE; @@ -134,29 +140,32 @@ get_iso8601_seconds (const gchar *text, gsize length, gdouble *value) for (; i < length; i++) { const gchar c = text[i]; - if (c < '0' || c > '9') + if (c < '0' || c > '9' || + v > (G_MAXUINT64 - (c - '0')) / 10 || + divisor > G_MAXUINT64 / 10) return FALSE; v = v * 10 + (c - '0'); divisor *= 10; } - *value = v / divisor; + *value = (gdouble) v / divisor; return TRUE; } static GDateTime * g_date_time_new_ordinal (GTimeZone *tz, gint year, gint ordinal_day, gint hour, gint minute, gdouble seconds) { - GDateTime *dt, *dt2; + GDateTime *dt; if (ordinal_day < 1 || ordinal_day > (GREGORIAN_LEAP (year) ? 366 : 365)) return NULL; dt = g_date_time_new (tz, year, 1, 1, hour, minute, seconds); - dt2 = g_date_time_add_days (dt, ordinal_day - 1); - g_date_time_unref (dt); + if (dt == NULL) + return NULL; + dt->days += ordinal_day - 1; - return dt2; + return dt; } static GDateTime * @@ -173,6 +182,8 @@ g_date_time_new_week (GTimeZone *tz, gint year, gint week, gint week_day, gint h return NULL; dt = g_date_time_new (tz, year, 1, 4, 0, 0, 0); + if (dt == NULL) + return NULL; g_date_time_get_week_number (dt, NULL, &jan4_week_day, NULL); g_date_time_unref (dt); @@ -260,7 +271,8 @@ parse_iso8601_date (const gchar *text, gsize length, static GTimeZone * parse_iso8601_timezone (const gchar *text, gsize length, gssize *tz_offset) { - gint i, tz_length, offset_sign = 1, offset_hours, offset_minutes; + gint i, tz_length, offset_hours, offset_minutes; + gint offset_sign = 1; GTimeZone *tz; /* UTC uses Z suffix */ @@ -282,7 +294,7 @@ parse_iso8601_timezone (const gchar *text, gsize length, gssize *tz_offset) tz_length = length - i; /* +hh:mm or -hh:mm */ - if (tz_length == 6 && text[i + 3] == ':') + if (tz_length == 6 && text[i+3] == ':') { if (!get_iso8601_int (text + i + 1, 2, &offset_hours) || !get_iso8601_int (text + i + 4, 2, &offset_minutes)) @@ -306,11 +318,20 @@ parse_iso8601_timezone (const gchar *text, gsize length, gssize *tz_offset) return NULL; *tz_offset = i; + /* BACKPORT DIFFERENCE: GLib uses g_time_zone_new_identifier() but that + * was new in 2.68, so stick to the deprecated g_time_zone_new(), which + * returns UTC on error */ tz = g_time_zone_new (text + i); /* Double-check that the GTimeZone matches our interpretation of the timezone. - * Failure would indicate a bug either here of in the GTimeZone code. */ - g_assert (g_time_zone_get_offset (tz, 0) == offset_sign * (offset_hours * 3600 + offset_minutes * 60)); + * This can fail because our interpretation is less strict than (for example) + * parse_time() in gtimezone.c, which restricts the range of the parsed + * integers. */ + if (tz == NULL || g_time_zone_get_offset (tz, 0) != offset_sign * (offset_hours * 3600 + offset_minutes * 60)) + { + g_clear_pointer (&tz, g_time_zone_unref); + return NULL; + } return tz; } @@ -344,7 +365,6 @@ parse_iso8601_time (const gchar *text, gsize length, return FALSE; } - GDateTime * flatpak_g_date_time_new_from_iso8601 (const gchar *text, GTimeZone *default_tz) { @@ -375,9 +395,9 @@ flatpak_g_date_time_new_from_iso8601 (const gchar *text, GTimeZone *default_tz) datetime = parse_iso8601_date (text, date_length, hour, minute, seconds, tz ? tz : default_tz); out: - if (tz != NULL) - g_time_zone_unref (tz); - return datetime; + if (tz != NULL) + g_time_zone_unref (tz); + return datetime; } #endif |