summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Ancell <robert.ancell@canonical.com>2020-04-06 17:05:46 +1200
committerRobert Ancell <robert.ancell@canonical.com>2020-04-07 09:44:38 +1200
commitc04c20c70aa29df07e27c43aed4ce4d31cdbdc20 (patch)
treebc1718c690cdbaaa5ee202a3bbb0fcf4adbf33d4
parent8e2dbdd934ede70015b4384132020c953e8b6c89 (diff)
downloadjson-glib-c04c20c70aa29df07e27c43aed4ce4d31cdbdc20.tar.gz
json-gvariant: Stop string to GVariant conversion failing due to unrelated errno changes
This was observed as failing due to some codepath inside g_variant_new_string setting errno to EAGAIN. Json Glib was erroneously detecting this in the checks designed to catch string to integer conversions. Solved by making errno only checked after the integer conversions.
-rw-r--r--json-glib/json-gvariant.c44
1 files changed, 33 insertions, 11 deletions
diff --git a/json-glib/json-gvariant.c b/json-glib/json-gvariant.c
index 8185cac..72df81d 100644
--- a/json-glib/json-gvariant.c
+++ b/json-glib/json-gvariant.c
@@ -840,6 +840,10 @@ gvariant_simple_from_string (const gchar *st,
{
GVariant *variant = NULL;
gchar *nptr = NULL;
+ gboolean conversion_error = FALSE;
+ gint64 signed_value;
+ guint64 unsigned_value;
+ gdouble double_value;
errno = 0;
@@ -851,43 +855,61 @@ gvariant_simple_from_string (const gchar *st,
else if (g_strcmp0 (st, "false") == 0)
variant = g_variant_new_boolean (FALSE);
else
- errno = 1;
+ conversion_error = TRUE;
break;
case G_VARIANT_CLASS_BYTE:
- variant = g_variant_new_byte (g_ascii_strtoll (st, &nptr, 10));
+ signed_value = g_ascii_strtoll (st, &nptr, 10);
+ conversion_error = errno != 0 || nptr == st;
+ variant = g_variant_new_byte (signed_value);
break;
case G_VARIANT_CLASS_INT16:
- variant = g_variant_new_int16 (g_ascii_strtoll (st, &nptr, 10));
+ signed_value = g_ascii_strtoll (st, &nptr, 10);
+ conversion_error = errno != 0 || nptr == st;
+ variant = g_variant_new_int16 (signed_value);
break;
case G_VARIANT_CLASS_UINT16:
- variant = g_variant_new_uint16 (g_ascii_strtoll (st, &nptr, 10));
+ signed_value = g_ascii_strtoll (st, &nptr, 10);
+ conversion_error = errno != 0 || nptr == st;
+ variant = g_variant_new_uint16 (signed_value);
break;
case G_VARIANT_CLASS_INT32:
- variant = g_variant_new_int32 (g_ascii_strtoll (st, &nptr, 10));
+ signed_value = g_ascii_strtoll (st, &nptr, 10);
+ conversion_error = errno != 0 || nptr == st;
+ variant = g_variant_new_int32 (signed_value);
break;
case G_VARIANT_CLASS_UINT32:
- variant = g_variant_new_uint32 (g_ascii_strtoull (st, &nptr, 10));
+ unsigned_value = g_ascii_strtoull (st, &nptr, 10);
+ conversion_error = errno != 0 || nptr == st;
+ variant = g_variant_new_uint32 (unsigned_value);
break;
case G_VARIANT_CLASS_INT64:
- variant = g_variant_new_int64 (g_ascii_strtoll (st, &nptr, 10));
+ signed_value = g_ascii_strtoll (st, &nptr, 10);
+ conversion_error = errno != 0 || nptr == st;
+ variant = g_variant_new_int64 (signed_value);
break;
case G_VARIANT_CLASS_UINT64:
- variant = g_variant_new_uint64 (g_ascii_strtoull (st, &nptr, 10));
+ unsigned_value = g_ascii_strtoull (st, &nptr, 10);
+ conversion_error = errno != 0 || nptr == st;
+ variant = g_variant_new_uint64 (unsigned_value);
break;
case G_VARIANT_CLASS_HANDLE:
- variant = g_variant_new_handle (strtol (st, &nptr, 10));
+ signed_value = strtol (st, &nptr, 10);
+ conversion_error = errno != 0 || nptr == st;
+ variant = g_variant_new_handle (signed_value);
break;
case G_VARIANT_CLASS_DOUBLE:
- variant = g_variant_new_double (g_ascii_strtod (st, &nptr));
+ double_value = g_ascii_strtod (st, &nptr);
+ conversion_error = errno != 0 || nptr == st;
+ variant = g_variant_new_double (double_value);
break;
case G_VARIANT_CLASS_STRING:
@@ -901,7 +923,7 @@ gvariant_simple_from_string (const gchar *st,
break;
}
- if (errno != 0 || nptr == st)
+ if (conversion_error)
{
g_set_error_literal (error,
G_IO_ERROR,