[json-glib: 1/2] json-gvariant: Stop string to GVariant conversion failing due to unrelated errno changes



commit 212f925a025f2beaf60040b416097833faa74446
Author: Robert Ancell <robert ancell canonical com>
Date:   Mon Apr 6 17:05:46 2020 +1200

    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.

 json-glib/json-gvariant.c | 33 ++++++++++++++++++++++++++-------
 1 file changed, 26 insertions(+), 7 deletions(-)
---
diff --git a/json-glib/json-gvariant.c b/json-glib/json-gvariant.c
index 8185cac..a86507a 100644
--- a/json-glib/json-gvariant.c
+++ b/json-glib/json-gvariant.c
@@ -840,6 +840,9 @@ gvariant_simple_from_string (const gchar    *st,
 {
   GVariant *variant = NULL;
   gchar *nptr = NULL;
+  gboolean conversion_error = FALSE;
+  gint64 signed_value;
+  guint64 unsigned_value;
 
   errno = 0;
 
@@ -851,39 +854,55 @@ 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:
+      signed_value = g_ascii_strtoll (st, &nptr, 10);
+      conversion_error = errno != 0 || nptr == st;
       variant = g_variant_new_uint16 (g_ascii_strtoll (st, &nptr, 10));
       break;
 
     case G_VARIANT_CLASS_INT32:
+      signed_value = g_ascii_strtoll (st, &nptr, 10);
+      conversion_error = errno != 0 || nptr == st;
       variant = g_variant_new_int32 (g_ascii_strtoll (st, &nptr, 10));
       break;
 
     case G_VARIANT_CLASS_UINT32:
-      variant = g_variant_new_uint32 (g_ascii_strtoull (st, &nptr, 10));
+      unsigned_value = g_ascii_strtoll (st, &nptr, 10);
+      conversion_error = errno != 0 || nptr == st;
+      variant = g_variant_new_uint32 (unsigned_value);
       break;
 
     case G_VARIANT_CLASS_INT64:
+      signed_value = g_ascii_strtoll (st, &nptr, 10);
+      conversion_error = errno != 0 || nptr == st;
       variant = g_variant_new_int64 (g_ascii_strtoll (st, &nptr, 10));
       break;
 
     case G_VARIANT_CLASS_UINT64:
-      variant = g_variant_new_uint64 (g_ascii_strtoull (st, &nptr, 10));
+      unsigned_value = g_ascii_strtoll (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:
@@ -901,7 +920,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,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]