mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-22 18:22:11 +01:00
Merge branch 'backport-4498-datetime-overflow-glib-2-82' into 'glib-2-82'
Backport !4498 “gdatetime: Fix integer overflow when parsing very long ISO8601 inputs” to glib-2-82 See merge request GNOME/glib!4499
This commit is contained in:
commit
c9b03bdb7c
@ -1393,12 +1393,16 @@ parse_iso8601_date (const gchar *text, gsize length,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Value returned in tz_offset is valid if and only if the function return value
|
||||||
|
* is non-NULL. */
|
||||||
static GTimeZone *
|
static GTimeZone *
|
||||||
parse_iso8601_timezone (const gchar *text, gsize length, gssize *tz_offset)
|
parse_iso8601_timezone (const gchar *text, gsize length, size_t *tz_offset)
|
||||||
{
|
{
|
||||||
gint i, tz_length, offset_hours, offset_minutes;
|
size_t tz_length;
|
||||||
|
gint offset_hours, offset_minutes;
|
||||||
gint offset_sign = 1;
|
gint offset_sign = 1;
|
||||||
GTimeZone *tz;
|
GTimeZone *tz;
|
||||||
|
const char *tz_start;
|
||||||
|
|
||||||
/* UTC uses Z suffix */
|
/* UTC uses Z suffix */
|
||||||
if (length > 0 && text[length - 1] == 'Z')
|
if (length > 0 && text[length - 1] == 'Z')
|
||||||
@ -1408,42 +1412,42 @@ parse_iso8601_timezone (const gchar *text, gsize length, gssize *tz_offset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Look for '+' or '-' of offset */
|
/* Look for '+' or '-' of offset */
|
||||||
for (i = length - 1; i >= 0; i--)
|
for (tz_length = 1; tz_length <= length; tz_length++)
|
||||||
if (text[i] == '+' || text[i] == '-')
|
if (text[length - tz_length] == '+' || text[length - tz_length] == '-')
|
||||||
{
|
{
|
||||||
offset_sign = text[i] == '-' ? -1 : 1;
|
offset_sign = text[length - tz_length] == '-' ? -1 : 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i < 0)
|
if (tz_length > length)
|
||||||
return NULL;
|
return NULL;
|
||||||
tz_length = length - i;
|
tz_start = text + length - tz_length;
|
||||||
|
|
||||||
/* +hh:mm or -hh:mm */
|
/* +hh:mm or -hh:mm */
|
||||||
if (tz_length == 6 && text[i+3] == ':')
|
if (tz_length == 6 && tz_start[3] == ':')
|
||||||
{
|
{
|
||||||
if (!get_iso8601_int (text + i + 1, 2, &offset_hours) ||
|
if (!get_iso8601_int (tz_start + 1, 2, &offset_hours) ||
|
||||||
!get_iso8601_int (text + i + 4, 2, &offset_minutes))
|
!get_iso8601_int (tz_start + 4, 2, &offset_minutes))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* +hhmm or -hhmm */
|
/* +hhmm or -hhmm */
|
||||||
else if (tz_length == 5)
|
else if (tz_length == 5)
|
||||||
{
|
{
|
||||||
if (!get_iso8601_int (text + i + 1, 2, &offset_hours) ||
|
if (!get_iso8601_int (tz_start + 1, 2, &offset_hours) ||
|
||||||
!get_iso8601_int (text + i + 3, 2, &offset_minutes))
|
!get_iso8601_int (tz_start + 3, 2, &offset_minutes))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* +hh or -hh */
|
/* +hh or -hh */
|
||||||
else if (tz_length == 3)
|
else if (tz_length == 3)
|
||||||
{
|
{
|
||||||
if (!get_iso8601_int (text + i + 1, 2, &offset_hours))
|
if (!get_iso8601_int (tz_start + 1, 2, &offset_hours))
|
||||||
return NULL;
|
return NULL;
|
||||||
offset_minutes = 0;
|
offset_minutes = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
*tz_offset = i;
|
*tz_offset = tz_start - text;
|
||||||
tz = g_time_zone_new_identifier (text + i);
|
tz = g_time_zone_new_identifier (tz_start);
|
||||||
|
|
||||||
/* Double-check that the GTimeZone matches our interpretation of the timezone.
|
/* Double-check that the GTimeZone matches our interpretation of the timezone.
|
||||||
* This can fail because our interpretation is less strict than (for example)
|
* This can fail because our interpretation is less strict than (for example)
|
||||||
@ -1462,11 +1466,11 @@ static gboolean
|
|||||||
parse_iso8601_time (const gchar *text, gsize length,
|
parse_iso8601_time (const gchar *text, gsize length,
|
||||||
gint *hour, gint *minute, gdouble *seconds, GTimeZone **tz)
|
gint *hour, gint *minute, gdouble *seconds, GTimeZone **tz)
|
||||||
{
|
{
|
||||||
gssize tz_offset = -1;
|
size_t tz_offset = 0;
|
||||||
|
|
||||||
/* Check for timezone suffix */
|
/* Check for timezone suffix */
|
||||||
*tz = parse_iso8601_timezone (text, length, &tz_offset);
|
*tz = parse_iso8601_timezone (text, length, &tz_offset);
|
||||||
if (tz_offset >= 0)
|
if (*tz != NULL)
|
||||||
length = tz_offset;
|
length = tz_offset;
|
||||||
|
|
||||||
/* hh:mm:ss(.sss) */
|
/* hh:mm:ss(.sss) */
|
||||||
@ -1544,7 +1548,8 @@ parse_iso8601_time (const gchar *text, gsize length,
|
|||||||
GDateTime *
|
GDateTime *
|
||||||
g_date_time_new_from_iso8601 (const gchar *text, GTimeZone *default_tz)
|
g_date_time_new_from_iso8601 (const gchar *text, GTimeZone *default_tz)
|
||||||
{
|
{
|
||||||
gint length, date_length = -1;
|
size_t length, date_length = 0;
|
||||||
|
gboolean date_length_set = FALSE;
|
||||||
gint hour = 0, minute = 0;
|
gint hour = 0, minute = 0;
|
||||||
gdouble seconds = 0.0;
|
gdouble seconds = 0.0;
|
||||||
GTimeZone *tz = NULL;
|
GTimeZone *tz = NULL;
|
||||||
@ -1555,11 +1560,14 @@ g_date_time_new_from_iso8601 (const gchar *text, GTimeZone *default_tz)
|
|||||||
/* Count length of string and find date / time separator ('T', 't', or ' ') */
|
/* Count length of string and find date / time separator ('T', 't', or ' ') */
|
||||||
for (length = 0; text[length] != '\0'; length++)
|
for (length = 0; text[length] != '\0'; length++)
|
||||||
{
|
{
|
||||||
if (date_length < 0 && (text[length] == 'T' || text[length] == 't' || text[length] == ' '))
|
if (!date_length_set && (text[length] == 'T' || text[length] == 't' || text[length] == ' '))
|
||||||
|
{
|
||||||
date_length = length;
|
date_length = length;
|
||||||
|
date_length_set = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (date_length < 0)
|
if (!date_length_set)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!parse_iso8601_time (text + date_length + 1, length - (date_length + 1),
|
if (!parse_iso8601_time (text + date_length + 1, length - (date_length + 1),
|
||||||
|
@ -866,6 +866,23 @@ test_GDateTime_new_from_iso8601 (void)
|
|||||||
* NaN */
|
* NaN */
|
||||||
dt = g_date_time_new_from_iso8601 ("0005306 000001,666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666600080000-00", NULL);
|
dt = g_date_time_new_from_iso8601 ("0005306 000001,666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666600080000-00", NULL);
|
||||||
g_assert_null (dt);
|
g_assert_null (dt);
|
||||||
|
|
||||||
|
/* Various invalid timezone offsets which look like they could be in
|
||||||
|
* `+hh:mm`, `-hh:mm`, `+hhmm`, `-hhmm`, `+hh` or `-hh` format */
|
||||||
|
dt = g_date_time_new_from_iso8601 ("2025-02-18T18:14:00+01:xx", NULL);
|
||||||
|
g_assert_null (dt);
|
||||||
|
dt = g_date_time_new_from_iso8601 ("2025-02-18T18:14:00+xx:00", NULL);
|
||||||
|
g_assert_null (dt);
|
||||||
|
dt = g_date_time_new_from_iso8601 ("2025-02-18T18:14:00+xx:xx", NULL);
|
||||||
|
g_assert_null (dt);
|
||||||
|
dt = g_date_time_new_from_iso8601 ("2025-02-18T18:14:00+01xx", NULL);
|
||||||
|
g_assert_null (dt);
|
||||||
|
dt = g_date_time_new_from_iso8601 ("2025-02-18T18:14:00+xx00", NULL);
|
||||||
|
g_assert_null (dt);
|
||||||
|
dt = g_date_time_new_from_iso8601 ("2025-02-18T18:14:00+xxxx", NULL);
|
||||||
|
g_assert_null (dt);
|
||||||
|
dt = g_date_time_new_from_iso8601 ("2025-02-18T18:14:00+xx", NULL);
|
||||||
|
g_assert_null (dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user