mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-11 23:16:14 +01:00
Merge branch 'wip/pwithnall/freebsd-math' into 'master'
gdatetime: Improve ISO 8601 parsing to avoid floating point checks See merge request GNOME/glib!1797
This commit is contained in:
commit
a4be8577ed
@ -1181,7 +1181,7 @@ static gboolean
|
|||||||
get_iso8601_seconds (const gchar *text, gsize length, gdouble *value)
|
get_iso8601_seconds (const gchar *text, gsize length, gdouble *value)
|
||||||
{
|
{
|
||||||
gsize i;
|
gsize i;
|
||||||
gdouble divisor = 1, v = 0;
|
guint64 divisor = 1, v = 0;
|
||||||
|
|
||||||
if (length < 2)
|
if (length < 2)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -1208,17 +1208,15 @@ get_iso8601_seconds (const gchar *text, gsize length, gdouble *value)
|
|||||||
for (; i < length; i++)
|
for (; i < length; i++)
|
||||||
{
|
{
|
||||||
const gchar c = text[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;
|
return FALSE;
|
||||||
v = v * 10 + (c - '0');
|
v = v * 10 + (c - '0');
|
||||||
divisor *= 10;
|
divisor *= 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
v = v / divisor;
|
*value = (gdouble) v / divisor;
|
||||||
if (!isfinite (v))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
*value = v;
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1590,7 +1588,7 @@ g_date_time_new (GTimeZone *tz,
|
|||||||
day < 1 || day > days_in_months[GREGORIAN_LEAP (year)][month] ||
|
day < 1 || day > days_in_months[GREGORIAN_LEAP (year)][month] ||
|
||||||
hour < 0 || hour > 23 ||
|
hour < 0 || hour > 23 ||
|
||||||
minute < 0 || minute > 59 ||
|
minute < 0 || minute > 59 ||
|
||||||
!isfinite (seconds) ||
|
isnan (seconds) ||
|
||||||
seconds < 0.0 || seconds >= 60.0)
|
seconds < 0.0 || seconds >= 60.0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -743,6 +743,14 @@ test_GDateTime_new_from_iso8601 (void)
|
|||||||
dt = g_date_time_new_from_iso8601 ("--0824T22:10:42Z", NULL);
|
dt = g_date_time_new_from_iso8601 ("--0824T22:10:42Z", NULL);
|
||||||
g_assert_null (dt);
|
g_assert_null (dt);
|
||||||
|
|
||||||
|
/* Seconds must be two digits. */
|
||||||
|
dt = g_date_time_new_from_iso8601 ("2016-08-10T22:10:4Z", NULL);
|
||||||
|
g_assert_null (dt);
|
||||||
|
|
||||||
|
/* Seconds must all be digits. */
|
||||||
|
dt = g_date_time_new_from_iso8601 ("2016-08-10T22:10:4aZ", NULL);
|
||||||
|
g_assert_null (dt);
|
||||||
|
|
||||||
/* Check subseconds work */
|
/* Check subseconds work */
|
||||||
dt = g_date_time_new_from_iso8601 ("2016-08-24T22:10:42.123456Z", NULL);
|
dt = g_date_time_new_from_iso8601 ("2016-08-24T22:10:42.123456Z", NULL);
|
||||||
ASSERT_DATE (dt, 2016, 8, 24);
|
ASSERT_DATE (dt, 2016, 8, 24);
|
||||||
@ -759,6 +767,28 @@ test_GDateTime_new_from_iso8601 (void)
|
|||||||
ASSERT_TIME (dt, 22, 10, 42, 123456);
|
ASSERT_TIME (dt, 22, 10, 42, 123456);
|
||||||
g_date_time_unref (dt);
|
g_date_time_unref (dt);
|
||||||
|
|
||||||
|
/* Subseconds must all be digits. */
|
||||||
|
dt = g_date_time_new_from_iso8601 ("2016-08-10T22:10:42.5aZ", NULL);
|
||||||
|
g_assert_null (dt);
|
||||||
|
|
||||||
|
/* Subseconds can be an arbitrary length, but must not overflow.
|
||||||
|
* The ASSERT_TIME() comparisons are constrained by only comparing up to
|
||||||
|
* microsecond granularity. */
|
||||||
|
dt = g_date_time_new_from_iso8601 ("2016-08-10T22:10:09.222222222222222222Z", NULL);
|
||||||
|
ASSERT_DATE (dt, 2016, 8, 10);
|
||||||
|
ASSERT_TIME (dt, 22, 10, 9, 222222);
|
||||||
|
g_date_time_unref (dt);
|
||||||
|
dt = g_date_time_new_from_iso8601 ("2016-08-10T22:10:09.2222222222222222222Z", NULL);
|
||||||
|
g_assert_null (dt);
|
||||||
|
|
||||||
|
/* Small numerator, large divisor when parsing the subseconds. */
|
||||||
|
dt = g_date_time_new_from_iso8601 ("2016-08-10T22:10:00.0000000000000000001Z", NULL);
|
||||||
|
ASSERT_DATE (dt, 2016, 8, 10);
|
||||||
|
ASSERT_TIME (dt, 22, 10, 0, 0);
|
||||||
|
g_date_time_unref (dt);
|
||||||
|
dt = g_date_time_new_from_iso8601 ("2016-08-10T22:10:00.00000000000000000001Z", NULL);
|
||||||
|
g_assert_null (dt);
|
||||||
|
|
||||||
/* We don't support times without minutes / seconds (valid ISO 8601) */
|
/* We don't support times without minutes / seconds (valid ISO 8601) */
|
||||||
dt = g_date_time_new_from_iso8601 ("2016-08-24T22Z", NULL);
|
dt = g_date_time_new_from_iso8601 ("2016-08-24T22Z", NULL);
|
||||||
g_assert_null (dt);
|
g_assert_null (dt);
|
||||||
@ -1280,8 +1310,18 @@ test_GDateTime_new_full (void)
|
|||||||
g_date_time_unref (dt);
|
g_date_time_unref (dt);
|
||||||
dt = g_date_time_new_utc (2016, 12, 32, 22, 10, 42);
|
dt = g_date_time_new_utc (2016, 12, 32, 22, 10, 42);
|
||||||
g_assert_null (dt);
|
g_assert_null (dt);
|
||||||
|
|
||||||
|
/* Seconds limits. */
|
||||||
dt = g_date_time_new_utc (2020, 12, 9, 14, 49, NAN);
|
dt = g_date_time_new_utc (2020, 12, 9, 14, 49, NAN);
|
||||||
g_assert_null (dt);
|
g_assert_null (dt);
|
||||||
|
dt = g_date_time_new_utc (2020, 12, 9, 14, 49, -0.1);
|
||||||
|
g_assert_null (dt);
|
||||||
|
dt = g_date_time_new_utc (2020, 12, 9, 14, 49, 60.0);
|
||||||
|
g_assert_null (dt);
|
||||||
|
|
||||||
|
/* Year limits */
|
||||||
|
dt = g_date_time_new_utc (10000, 1, 1, 0, 0, 0);
|
||||||
|
dt = g_date_time_new_utc (0, 1, 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user