Commit 5d7f4b8f authored by Philip Withnall's avatar Philip Withnall
Browse files

gdatetime: Remove floating point from seconds parsing code



Rather than parsing the seconds in an ISO 8601 date/time using a pair of
floating point numbers (numerator and denominator), use two integers
instead. This avoids issues around floating point precision, and also
makes it easier to check for potential overflow from overlong inputs.

This last point means that the `isfinite()` check can be removed, as it
was covering the case where a NAN was generated, which isn’t now
possible using integer arithmetic.
Signed-off-by: Philip Withnall's avatarPhilip Withnall <pwithnall@endlessos.org>
parent a28b3c9d
...@@ -1181,7 +1181,7 @@ static gboolean ...@@ -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) ...@@ -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;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment