[PATCH] lib: fwts_json: fix output so that it is machine parsable (LP: #1902249)

Colin King colin.king at canonical.com
Fri Oct 30 17:49:13 UTC 2020


From: Colin Ian King <colin.king at canonical.com>

Currenty the json output is incorrectly places a trailing comma at
the end of collections.  Fix this by re-working the output to
not emit commas where they are not required.  Also escape the
output strings so they can be read by json parsers.

Fixes: 1a663dd3b37 ("Replace json-c library with minimal replacement")
Signed-off-by: Colin Ian King <colin.king at canonical.com>
---
 src/lib/src/fwts_json.c | 104 ++++++++++++++++++++++++++++++++++------
 1 file changed, 89 insertions(+), 15 deletions(-)

diff --git a/src/lib/src/fwts_json.c b/src/lib/src/fwts_json.c
index 8f2c396d..130e5ccb 100644
--- a/src/lib/src/fwts_json.c
+++ b/src/lib/src/fwts_json.c
@@ -755,6 +755,44 @@ static char *str_indent(char *str, int indent)
 	return str_append(str, buf);
 }
 
+static bool char_escape(const int ch)
+{
+	switch (ch) {
+	case '"':
+	case '\b':
+	case '\f':
+	case '\n':
+	case '\r':
+	case '\t':
+		return true;
+	default:
+		break;
+	}
+	return false;
+}
+
+static char *str_escape(char *oldstr)
+{
+	char *oldptr, *newstr, *newptr;
+	ssize_t n;
+
+	for (n = 0, oldptr = oldstr; *oldptr; oldptr++, n++)
+		if (char_escape(*oldptr))
+			n++;
+
+	newstr = malloc(n + 1);
+	if (!newstr)
+		return NULL;
+
+	for (oldptr = oldstr, newptr = newstr; *oldptr; oldptr++, newptr++) {
+		if (char_escape(*oldptr))
+			*(newptr++) = '\\';
+		*newptr = *oldptr;
+	}
+	*newptr = '\0';
+	return newstr;
+}
+
 /*
  *  json_object_to_json_string_indent()
  *	turn a simplified fwts json object into a C string, returns
@@ -766,6 +804,7 @@ static char *json_object_to_json_string_indent(json_object *obj, int indent)
 	int i;
 	json_object **obj_ptr;
 	char *str = NULL;
+	char *tmp;
 	char buf[64];
 
 	if (!obj)
@@ -775,9 +814,6 @@ static char *json_object_to_json_string_indent(json_object *obj, int indent)
 		str = str_indent(str, indent);
 		if (!str)
 			return NULL;
-		str = str_append(str, "{\n");
-		if (!str)
-			return NULL;
 	}
 
         if (obj->key) {
@@ -797,15 +833,33 @@ static char *json_object_to_json_string_indent(json_object *obj, int indent)
 
 	switch (obj->type) {
 	case type_array:
-		str = str_append(str, "[\n");
+		str = str_append(str, "\n");
+		if (!str)
+			return NULL;
+		str = str_indent(str, indent);
+		if (!str)
+			return NULL;
+		str = str_append(str, "[");
 		if (!str)
 			return NULL;
 
 		obj_ptr = (json_object **)obj->u.ptr;
 		if (obj_ptr) {
 			for (i = 0; i < obj->length; i++) {
-				char *obj_str = json_object_to_json_string_indent(obj_ptr[i], indent + 1);
-
+				char *obj_str;
+
+				if (i) {
+					str = str_append(str, "\n");
+					if (!str)
+						return NULL;
+					str = str_indent(str, indent + 1);
+					if (!str)
+						return NULL;
+					str = str_append(str, ",");
+					if (!str)
+						return NULL;
+				}
+				obj_str = json_object_to_json_string_indent(obj_ptr[i], indent + 1);
 				if (!obj_str) {
 					free(str);
 					return NULL;
@@ -821,17 +875,30 @@ static char *json_object_to_json_string_indent(json_object *obj, int indent)
 		str = str_indent(str, indent);
 		if (!str)
 			return NULL;
-		str = str_append(str, "]\n");
+		str = str_append(str, "]");
 		if (!str)
 			return NULL;
 		break;
 
 	case type_object:
+		str = str_append(str, "\n");
+		if (!str)
+			return NULL;
+		str = str_indent(str, indent);
+		if (!str)
+			return NULL;
+		str = str_append(str, "{");
+		if (!str)
+			return NULL;
 		obj_ptr = (json_object **)obj->u.ptr;
 		if (obj_ptr) {
 			for (i = 0; i < obj->length; i++) {
-				char *obj_str = json_object_to_json_string_indent(obj_ptr[i], indent + 1);
+				char *obj_str;
 
+				str = str_append(str, (i == 0) ? "\n" : ",\n");
+				if (!str)
+					return NULL;
+				obj_str = json_object_to_json_string_indent(obj_ptr[i], indent + 1);
 				if (!obj_str) {
 					free(str);
 					return NULL;
@@ -841,6 +908,13 @@ static char *json_object_to_json_string_indent(json_object *obj, int indent)
 					return NULL;
 			}
 		}
+		str = str_append(str, "\n");
+		if (!str)
+			return NULL;
+		str = str_indent(str, indent);
+		if (!str)
+			return NULL;
+		str = str_append(str, "}");
 		if (!str)
 			return NULL;
 		break;
@@ -849,22 +923,25 @@ static char *json_object_to_json_string_indent(json_object *obj, int indent)
 		str = str_append(str, "\"");
 		if (!str)
 			return NULL;
-		str = str_append(str, (char *)obj->u.ptr);
+		tmp = str_escape((char *)obj->u.ptr);
+		if (!tmp)
+			return NULL;
+		str = str_append(str, tmp);
 		if (!str)
 			return NULL;
-		str = str_append(str, "\",\n");
+		str = str_append(str, "\"");
 		if (!str)
 			return NULL;
 		break;
 
 	case type_null:
-		str = str_append(str, "(null)\n");
+		str = str_append(str, "(null)");
 		if (!str)
 			return NULL;
 		break;
 
 	case type_int:
-		snprintf(buf, sizeof(buf), "%d,\n", obj->u.intval);
+		snprintf(buf, sizeof(buf), "%d", obj->u.intval);
 		str = str_append(str, buf);
 		if (!str)
 			return NULL;
@@ -877,9 +954,6 @@ static char *json_object_to_json_string_indent(json_object *obj, int indent)
 		str = str_indent(str, indent);
 		if (!str)
 			return NULL;
-		str = str_append(str, "},\n");
-		if (!str)
-			return NULL;
 	}
 	return str;
 }
-- 
2.27.0




More information about the fwts-devel mailing list