From eb2f29b7fd9c889a8d30600acbe10cf440eba394 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 4 Feb 2020 21:18:31 -0800 Subject: [PATCH 1/1] Make the JSON code easier to analyze 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 --- json.c | 68 ++++++++++++++++------------ json.h | 140 ++++++++++++++++++++++++++++++++++++++++++++++++--------- stat.c | 2 +- 3 files changed, 159 insertions(+), 51 deletions(-) diff --git a/json.c b/json.c index e2819a65..cd3d5d74 100644 --- 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 bcc712cd..09c2f187 100644 --- 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 69d57b69..2c59c0f6 100644 --- 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]); -- 2.25.1