gdatetime: Disallow NAN as a number of seconds in a GDateTime

The fiendish thing about NAN is that it never compares TRUE against
anything, so the limit checks `seconds < 0.0 || seconds >= 60.0` were
never triggering.

oss-fuzz#28473

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This commit is contained in:
Philip Withnall 2020-12-09 14:50:02 +00:00
parent 737a853f8d
commit c3805d74ba
2 changed files with 16 additions and 1 deletions

View File

@ -52,6 +52,7 @@
#define _GNU_SOURCE 1 #define _GNU_SOURCE 1
#endif #endif
#include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -1213,7 +1214,11 @@ get_iso8601_seconds (const gchar *text, gsize length, gdouble *value)
divisor *= 10; divisor *= 10;
} }
*value = v / divisor; v = v / divisor;
if (!isfinite (v))
return FALSE;
*value = v;
return TRUE; return TRUE;
} }
@ -1585,6 +1590,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) ||
seconds < 0.0 || seconds >= 60.0) seconds < 0.0 || seconds >= 60.0)
return NULL; return NULL;

View File

@ -18,6 +18,7 @@
#include "config.h" #include "config.h"
#include <math.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <gi18n.h> #include <gi18n.h>
@ -799,6 +800,12 @@ test_GDateTime_new_from_iso8601 (void)
/* Timezone hours two digits */ /* Timezone hours two digits */
dt = g_date_time_new_from_iso8601 ("2016-08-24T22-2Z", NULL); dt = g_date_time_new_from_iso8601 ("2016-08-24T22-2Z", NULL);
g_assert_null (dt); g_assert_null (dt);
/* Ordinal date (YYYYDDD), space separator, and then time as HHMMSS,SSS
* The interesting bit is that the seconds field is so long as to parse as
* NaN */
dt = g_date_time_new_from_iso8601 ("0005306 000001,666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666600080000-00", NULL);
g_assert_null (dt);
} }
typedef struct { typedef struct {
@ -1273,6 +1280,8 @@ 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);
dt = g_date_time_new_utc (2020, 12, 9, 14, 49, NAN);
g_assert_null (dt);
} }
static void static void