[libvirt] [PATCH] json: fix interface locale dependency

Martin Kletzander mkletzan at redhat.com
Mon Aug 6 08:12:17 UTC 2012


libvirt creates invalid commands if wrong locale is selected.  For
example with locale that uses comma as a decimal point, JSON commands
created with decimal numbers are invalid because comma separates the
entries in JSON.

But even when decimal point is affected, grouping is not, because for
grouping to be enabled with *printf, there has to be a apostrophe flag
specified (and supported).
---
Fortunately, there should be no other place where output-formatting is
affected by this problem.

I tried to change this in various ways with this posted one being the
cleanest from my point of view, because:
 - setting locale is per-proccess, not per-thread (not thread-safe)
 - there is no number parsing that mangles the output number because
 of floating point precision

 src/util/json.c |   23 +++++++++++++++++++++--
 1 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/src/util/json.c b/src/util/json.c
index 5132989..753a548 100644
--- a/src/util/json.c
+++ b/src/util/json.c
@@ -23,6 +23,8 @@

 #include <config.h>

+#include <locale.h>
+
 #include "json.h"
 #include "memory.h"
 #include "virterror_internal.h"
@@ -44,7 +46,6 @@
 /* XXX fixme */
 #define VIR_FROM_THIS VIR_FROM_NONE

-
 typedef struct _virJSONParserState virJSONParserState;
 typedef virJSONParserState *virJSONParserStatePtr;
 struct _virJSONParserState {
@@ -200,9 +201,27 @@ virJSONValuePtr virJSONValueNewNumberUlong(unsigned long long data)
 virJSONValuePtr virJSONValueNewNumberDouble(double data)
 {
     virJSONValuePtr val = NULL;
-    char *str;
+    char *str, *radix, *tmp;
+
     if (virAsprintf(&str, "%lf", data) < 0)
         return NULL;
+
+    /* because printing double is locale-dependent, we could end up
+     * with invalid JSON code, so we have to do something like this */
+    radix = localeconv()->decimal_point;
+    tmp = strstr(str, radix);
+    if (tmp) {
+        *tmp = '.';
+        if (strlen(radix) > 1) {
+            /* if the current locale specifies more characters as
+             * decimal point then cover the others with decimal
+             * numbers */
+            memcpy(tmp + 1,
+                   tmp + strlen(radix),
+                   strlen(str) - (tmp - str));
+        }
+    }
+
     val = virJSONValueNewNumber(str);
     VIR_FREE(str);
     return val;
--
1.7.8.6




More information about the libvir-list mailing list