[PATCH 003/103] virJSONValueObjectAddVArgs: Add new convertors for allocated strings

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

 



The 'f' and 'F' convertors add a string value to the JSON value object
and free the passed pointer. This is helpful in case we need to e.g. add
single use formatted values:

 virJSONValueObjectAdd(props,
                       "f:test1", g_strdup_printf("%s-test1", blah),
                       "F:test2", virGetStringAndReportErrorOnNull(),
                       NULL);

With 'F' if the passed string is NULL no additional error is reported so
the error is passed through.

To prevent leaking the strings on reasonable failures we add an 'err'
variable which skips the implementation of the conversions, but keeps
iterating through the arguments.

On hard programming errors (bad key format) the string is leaked but
that should not be a problem in practice.

Signed-off-by: Peter Krempa <pkrempa@xxxxxxxxxx>
---
 src/util/virjson.c | 82 ++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 68 insertions(+), 14 deletions(-)

diff --git a/src/util/virjson.c b/src/util/virjson.c
index d7e72af8f9..4d9cd5629a 100644
--- a/src/util/virjson.c
+++ b/src/util/virjson.c
@@ -112,6 +112,8 @@ virJSONValueGetType(const virJSONValue *value)
  * Explanation of type codes:
  * s: string value, must be non-null
  * S: string value, omitted if null
+ * f: string value, passed pointer is freed, error reported if NULL
+ * F: string value, passed pointer is freed, no error reported if NULL
  *
  * i: signed integer value
  * j: signed integer value, error if negative
@@ -155,6 +157,7 @@ int
 virJSONValueObjectAddVArgs(virJSONValue *obj,
                            va_list args)
 {
+    bool err = false;
     char type;
     char *key;
     int rc;
@@ -173,17 +176,30 @@ virJSONValueObjectAddVArgs(virJSONValue *obj,

         /* This doesn't support maps, but no command uses those.  */
         switch (type) {
+        case 'f':
+        case 'F':
         case 'S':
         case 's': {
             char *val = va_arg(args, char *);
+            g_autofree char *valf = NULL;
+
+            if (type == 'f' || type == 'F')
+                valf = val;
+
+            if (err)
+                continue;
+
             if (!val) {
                 if (type == 'S')
                     continue;

-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("argument key '%s' must not have null value"),
-                               key);
-                return -1;
+                if (type != 'F') {
+                    virReportError(VIR_ERR_INTERNAL_ERROR,
+                                   _("argument key '%s' must not have null value"),
+                                   key);
+                }
+                err = true;
+                continue;
             }
             rc = virJSONValueObjectAppendString(obj, key, val);
         }   break;
@@ -195,11 +211,15 @@ virJSONValueObjectAddVArgs(virJSONValue *obj,
         case 'i': {
             int val = va_arg(args, int);

+            if (err)
+                continue;
+
             if (val < 0 && (type == 'j' || type == 'y')) {
                 virReportError(VIR_ERR_INTERNAL_ERROR,
                                _("argument key '%s' must not be negative"),
                                key);
-                return -1;
+                err = true;
+                continue;
             }

             if (val == 0 && (type == 'z' || type == 'y'))
@@ -215,6 +235,9 @@ virJSONValueObjectAddVArgs(virJSONValue *obj,
         case 'u': {
             unsigned int val = va_arg(args, unsigned int);

+            if (err)
+                continue;
+
             if (!val && type == 'p')
                 continue;

@@ -227,11 +250,15 @@ virJSONValueObjectAddVArgs(virJSONValue *obj,
         case 'I': {
             long long val = va_arg(args, long long);

+            if (err)
+                continue;
+
             if (val < 0 && (type == 'J' || type == 'Y')) {
                 virReportError(VIR_ERR_INTERNAL_ERROR,
                                _("argument key '%s' must not be negative"),
                                key);
-                return -1;
+                err = true;
+                continue;
             }

             if (!val && (type == 'Z' || type == 'Y'))
@@ -249,6 +276,9 @@ virJSONValueObjectAddVArgs(virJSONValue *obj,
              */
             long long val = va_arg(args, long long);

+            if (err)
+                continue;
+
             if (!val && type == 'P')
                 continue;

@@ -257,6 +287,10 @@ virJSONValueObjectAddVArgs(virJSONValue *obj,

         case 'd': {
             double val = va_arg(args, double);
+
+            if (err)
+                continue;
+
             rc = virJSONValueObjectAppendNumberDouble(obj, key, val);
         }   break;

@@ -265,6 +299,9 @@ virJSONValueObjectAddVArgs(virJSONValue *obj,
         case 'b': {
             int val = va_arg(args, int);

+            if (err)
+                continue;
+
             if (!val && type == 'B')
                 continue;

@@ -282,6 +319,9 @@ virJSONValueObjectAddVArgs(virJSONValue *obj,
         }   break;

         case 'n': {
+            if (err)
+                continue;
+
             rc = virJSONValueObjectAppendNull(obj, key);
         }   break;

@@ -289,6 +329,9 @@ virJSONValueObjectAddVArgs(virJSONValue *obj,
         case 'a': {
             virJSONValue **val = va_arg(args, virJSONValue **);

+            if (err)
+                continue;
+
             if (!(*val)) {
                 if (type == 'A')
                     continue;
@@ -296,7 +339,8 @@ virJSONValueObjectAddVArgs(virJSONValue *obj,
                 virReportError(VIR_ERR_INTERNAL_ERROR,
                                _("argument key '%s' must not have null value"),
                                key);
-                return -1;
+                err = true;
+                continue;
             }

             rc = virJSONValueObjectAppend(obj, key, val);
@@ -308,6 +352,9 @@ virJSONValueObjectAddVArgs(virJSONValue *obj,
             g_autoptr(virJSONValue) jsonMap = virJSONValueNewArray();
             ssize_t pos = -1;

+            if (err)
+                continue;
+
             if (!map) {
                 if (type == 'M')
                     continue;
@@ -315,18 +362,20 @@ virJSONValueObjectAddVArgs(virJSONValue *obj,
                 virReportError(VIR_ERR_INTERNAL_ERROR,
                                _("argument key '%s' must not have null value"),
                                key);
-                return -1;
+                err = true;
+                continue;
             }

             while ((pos = virBitmapNextSetBit(map, pos)) > -1) {
                 g_autoptr(virJSONValue) newelem = virJSONValueNewNumberLong(pos);

-                if (virJSONValueArrayAppend(jsonMap, &newelem) < 0)
-                    return -1;
+                if (virJSONValueArrayAppend(jsonMap, &newelem) < 0) {
+                    err = true;
+                    continue;
+                }
             }

-            if ((rc = virJSONValueObjectAppend(obj, key, &jsonMap)) < 0)
-                return -1;
+            rc = virJSONValueObjectAppend(obj, key, &jsonMap);
         } break;

         default:
@@ -335,10 +384,15 @@ virJSONValueObjectAddVArgs(virJSONValue *obj,
             return -1;
         }

-        if (rc < 0)
-            return -1;
+        if (rc < 0) {
+            err = true;
+            continue;
+        }
     }

+    if (err)
+        return -1;
+
     /* verify that we added at least one key-value pair */
     if (virJSONValueObjectKeysNumber(obj) == 0)
         return 0;
-- 
2.31.1




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux