Make the JSON code easier to analyze
authorBart Van Assche <bvanassche@acm.org>
Wed, 5 Feb 2020 05:18:31 +0000 (21:18 -0800)
committerBart Van Assche <bvanassche@acm.org>
Thu, 6 Feb 2020 03:04:38 +0000 (19:04 -0800)
Coverity reports the following false positive for the JSON code in stat.c:

CID 284826 (#1 of 1): Resource leak (RESOURCE_LEAK)
17. leaked_storage: Variable percentile_object going out of scope leaks the storage it points to.

Suppress this false positive by making the JSON code easier to analyze. The
changes in this patch are as follows:
- Change the macros in json.h into inline functions such that the compiler
  performs argument type verification at compile time.
- Pass a struct json_value pointer to json_*_add_value_type() instead of
  using varargs.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
json.c
json.h
stat.c

diff --git a/json.c b/json.c
index e2819a65ba6a3236f7a3dba8a506eca07ddfb0fc..cd3d5d74db12aab06409e523b95d9eed3c013682 100644 (file)
--- a/json.c
+++ b/json.c
@@ -194,25 +194,31 @@ static int json_object_add_pair(struct json_object *obj, struct json_pair *pair)
        return 0;
 }
 
-int json_object_add_value_type(struct json_object *obj, const char *name, int type, ...)
+int json_object_add_value_type(struct json_object *obj, const char *name,
+                              const struct json_value *arg)
 {
        struct json_value *value;
        struct json_pair *pair;
-       va_list args;
        int ret;
 
-       va_start(args, type);
-       if (type == JSON_TYPE_STRING)
-               value = json_create_value_string(va_arg(args, char *));
-       else if (type == JSON_TYPE_INTEGER)
-               value = json_create_value_int(va_arg(args, long long));
-       else if (type == JSON_TYPE_FLOAT)
-               value = json_create_value_float(va_arg(args, double));
-       else if (type == JSON_TYPE_OBJECT)
-               value = json_create_value_object(va_arg(args, struct json_object *));
-       else
-               value = json_create_value_array(va_arg(args, struct json_array *));
-       va_end(args);
+       switch (arg->type) {
+       case JSON_TYPE_STRING:
+               value = json_create_value_string(arg->string);
+               break;
+       case JSON_TYPE_INTEGER:
+               value = json_create_value_int(arg->integer_number);
+               break;
+       case JSON_TYPE_FLOAT:
+               value = json_create_value_float(arg->float_number);
+               break;
+       case JSON_TYPE_OBJECT:
+               value = json_create_value_object(arg->object);
+               break;
+       default:
+       case JSON_TYPE_ARRAY:
+               value = json_create_value_array(arg->array);
+               break;
+       }
 
        if (!value)
                return ENOMEM;
@@ -230,24 +236,30 @@ int json_object_add_value_type(struct json_object *obj, const char *name, int ty
        return 0;
 }
 
-int json_array_add_value_type(struct json_array *array, int type, ...)
+int json_array_add_value_type(struct json_array *array,
+                             const struct json_value *arg)
 {
        struct json_value *value;
-       va_list args;
        int ret;
 
-       va_start(args, type);
-       if (type == JSON_TYPE_STRING)
-               value = json_create_value_string(va_arg(args, char *));
-       else if (type == JSON_TYPE_INTEGER)
-               value = json_create_value_int(va_arg(args, long long));
-       else if (type == JSON_TYPE_FLOAT)
-               value = json_create_value_float(va_arg(args, double));
-       else if (type == JSON_TYPE_OBJECT)
-               value = json_create_value_object(va_arg(args, struct json_object *));
-       else
-               value = json_create_value_array(va_arg(args, struct json_array *));
-       va_end(args);
+       switch (arg->type) {
+       case JSON_TYPE_STRING:
+               value = json_create_value_string(arg->string);
+               break;
+       case JSON_TYPE_INTEGER:
+               value = json_create_value_int(arg->integer_number);
+               break;
+       case JSON_TYPE_FLOAT:
+               value = json_create_value_float(arg->float_number);
+               break;
+       case JSON_TYPE_OBJECT:
+               value = json_create_value_object(arg->object);
+               break;
+       default:
+       case JSON_TYPE_ARRAY:
+               value = json_create_value_array(arg->array);
+               break;
+       }
 
        if (!value)
                return ENOMEM;
diff --git a/json.h b/json.h
index bcc712cd4d414b91aeb923ae69c3b9bcd8a4c0b9..09c2f18715c61911dfda6dacc860ef44475a9b3b 100644 (file)
--- a/json.h
+++ b/json.h
@@ -49,28 +49,124 @@ struct json_array *json_create_array(void);
 
 void json_free_object(struct json_object *obj);
 
-int json_object_add_value_type(struct json_object *obj, const char *name, int type, ...);
-#define json_object_add_value_int(obj, name, val) \
-       json_object_add_value_type((obj), name, JSON_TYPE_INTEGER, (long long) (val))
-#define json_object_add_value_float(obj, name, val) \
-       json_object_add_value_type((obj), name, JSON_TYPE_FLOAT, (val))
-#define json_object_add_value_string(obj, name, val) \
-       json_object_add_value_type((obj), name, JSON_TYPE_STRING, (val))
-#define json_object_add_value_object(obj, name, val) \
-       json_object_add_value_type((obj), name, JSON_TYPE_OBJECT, (val))
-#define json_object_add_value_array(obj, name, val) \
-       json_object_add_value_type((obj), name, JSON_TYPE_ARRAY, (val))
-int json_array_add_value_type(struct json_array *array, int type, ...);
-#define json_array_add_value_int(obj, val) \
-       json_array_add_value_type((obj), JSON_TYPE_INTEGER, (val))
-#define json_array_add_value_float(obj, val) \
-       json_array_add_value_type((obj), JSON_TYPE_FLOAT, (val))
-#define json_array_add_value_string(obj, val) \
-       json_array_add_value_type((obj), JSON_TYPE_STRING, (val))
-#define json_array_add_value_object(obj, val) \
-       json_array_add_value_type((obj), JSON_TYPE_OBJECT, (val))
-#define json_array_add_value_array(obj, val) \
-       json_array_add_value_type((obj), JSON_TYPE_ARRAY, (val))
+int json_object_add_value_type(struct json_object *obj, const char *name,
+                              const struct json_value *val);
+
+static inline int json_object_add_value_int(struct json_object *obj,
+                                           const char *name, long long val)
+{
+       struct json_value arg = {
+               .type = JSON_TYPE_INTEGER,
+               .integer_number = val,
+       };
+
+       return json_object_add_value_type(obj, name, &arg);
+}
+
+static inline int json_object_add_value_float(struct json_object *obj,
+                                             const char *name, double val)
+{
+       struct json_value arg = {
+               .type = JSON_TYPE_FLOAT,
+               .float_number = val,
+       };
+
+       return json_object_add_value_type(obj, name, &arg);
+}
+
+static inline int json_object_add_value_string(struct json_object *obj,
+                                              const char *name,
+                                              const char *val)
+{
+       struct json_value arg = {
+               .type = JSON_TYPE_STRING,
+               .string = (char *)val,
+       };
+
+       return json_object_add_value_type(obj, name, &arg);
+}
+
+static inline int json_object_add_value_object(struct json_object *obj,
+                                              const char *name,
+                                              struct json_object *val)
+{
+       struct json_value arg = {
+               .type = JSON_TYPE_OBJECT,
+               .object = val,
+       };
+
+       return json_object_add_value_type(obj, name, &arg);
+}
+
+static inline int json_object_add_value_array(struct json_object *obj,
+                                             const char *name,
+                                             struct json_array *val)
+{
+       struct json_value arg = {
+               .type = JSON_TYPE_ARRAY,
+               .array = val,
+       };
+
+       return json_object_add_value_type(obj, name, &arg);
+}
+
+int json_array_add_value_type(struct json_array *array,
+                             const struct json_value *val);
+
+static inline int json_array_add_value_int(struct json_array *obj,
+                                          long long val)
+{
+       struct json_value arg = {
+               .type = JSON_TYPE_INTEGER,
+               .integer_number = val,
+       };
+
+       return json_array_add_value_type(obj, &arg);
+}
+
+static inline int json_array_add_value_float(struct json_array *obj,
+                                            double val)
+{
+       struct json_value arg = {
+               .type = JSON_TYPE_FLOAT,
+               .float_number = val,
+       };
+
+       return json_array_add_value_type(obj, &arg);
+}
+
+static inline int json_array_add_value_string(struct json_array *obj,
+                                             const char *val)
+{
+       struct json_value arg = {
+               .type = JSON_TYPE_STRING,
+               .string = (char *)val,
+       };
+
+       return json_array_add_value_type(obj, &arg);
+}
+
+static inline int json_array_add_value_object(struct json_array *obj,
+                                             struct json_object *val)
+{
+       struct json_value arg = {
+               .type = JSON_TYPE_OBJECT,
+               .object = val,
+       };
+
+       return json_array_add_value_type(obj, &arg);
+}
+
+static inline int json_array_add_value_array(struct json_array *obj,
+                                            struct json_array *val)
+{
+       struct json_value arg = {
+               .type = JSON_TYPE_ARRAY,
+               .array = val,
+       };
+
+       return json_array_add_value_type(obj, &arg);
+}
 
 #define json_array_last_value_object(obj) \
        (obj->values[obj->value_cnt - 1]->object)
diff --git a/stat.c b/stat.c
index 69d57b696ce3ab2b7782210012bcd4002a40433e..2c59c0f6c0f1fa990694b48a0e09ff168e406da5 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -950,7 +950,7 @@ void json_array_add_disk_util(struct disk_util_stat *dus,
        obj = json_create_object();
        json_array_add_value_object(array, obj);
 
-       json_object_add_value_string(obj, "name", dus->name);
+       json_object_add_value_string(obj, "name", (const char *)dus->name);
        json_object_add_value_int(obj, "read_ios", dus->s.ios[0]);
        json_object_add_value_int(obj, "write_ios", dus->s.ios[1]);
        json_object_add_value_int(obj, "read_merges", dus->s.merges[0]);