Blob Blame History Raw
From 3d7abc2131bcf4dd2dc21428ea2c7fee6dd7be94 Mon Sep 17 00:00:00 2001
From: Tomas Heinrich <theinric@redhat.com>
Date: Fri, 1 Aug 2014 13:58:10 +0200
Subject: [PATCH] imjournal: escape zero bytes in fields' values

---
 plugins/imjournal/imjournal.c | 86 +++++++++++++++++++++++--------------------
 1 file changed, 46 insertions(+), 40 deletions(-)

diff --git a/plugins/imjournal/imjournal.c b/plugins/imjournal/imjournal.c
index b0b034c..b6910e8 100755
--- a/plugins/imjournal/imjournal.c
+++ b/plugins/imjournal/imjournal.c
@@ -135,6 +135,31 @@ static rsRetVal facilityHdlr(uchar **pp, void *pVal)
 }
 
 
+/* Currently just replaces '\0' with ' '. Not doing so would cause
+ * the value to be truncated. New space is allocated for the resulting
+ * string.
+ */
+static rsRetVal
+sanitizeValue(const char *in, size_t len, char **out)
+{
+	char *buf, *p;
+	DEFiRet;
+
+	CHKmalloc(p = buf = malloc(len + 1));
+	memcpy(buf, in, len);
+	buf[len] = '\0';
+
+	while ((p = memchr(p, '\0', len + buf - p)) != NULL) {
+		*p++ = ' ';
+	}
+
+	*out = buf;
+
+finalize_it:
+	RETiRet;
+}
+
+
 /* enqueue the the journal message into the message queue.
  * The provided msg string is not freed - thus must be done
  * by the caller.
@@ -195,10 +220,9 @@ readjournal() {
 	int r;
 
 	/* Information from messages */
-	char *message;
-	char *sys_pid;
+	char *message = NULL;
 	char *sys_iden;
-	char *sys_iden_help;
+	char *sys_iden_help = NULL;
 
 	const void *get;
 	const void *pidget;
@@ -208,8 +232,6 @@ readjournal() {
 
 	const void *equal_sign;
 	struct json_object *jval;
-	char *data;
-	char *name;
 	size_t l;
 
 	long prefixlen = 0;
@@ -221,11 +243,7 @@ readjournal() {
 	if (sd_journal_get_data(j, "MESSAGE", &get, &length) < 0) {
 		message = strdup("");
 	} else {
-		message = strndup(get+8, length-8);
-		if (message == NULL) {
-			iRet = RS_RET_OUT_OF_MEMORY;
-			goto ret;
-		}
+		CHKiRet(sanitizeValue(((const char *)get) + 8, length - 8, &message));
 	}
 
 	/* Get message severity ("priority" in journald's terminology) */
@@ -264,43 +282,36 @@ readjournal() {
 
 	/* Get message identifier, client pid and add ':' */
 	if (sd_journal_get_data(j, "SYSLOG_IDENTIFIER", &get, &length) >= 0) {
-		sys_iden = strndup(get+18, length-18);
+		CHKiRet(sanitizeValue(((const char *)get) + 18, length - 18, &sys_iden));
 	} else {
-		sys_iden = strdup("journal");
-	}
-	if (sys_iden == NULL) {
-		iRet = RS_RET_OUT_OF_MEMORY;
-		goto free_message;
+		CHKmalloc(sys_iden = strdup("journal"));
 	}
 
 	if (sd_journal_get_data(j, "SYSLOG_PID", &pidget, &pidlength) >= 0) {
-		sys_pid = strndup(pidget+11, pidlength-11);
-		if (sys_pid == NULL) {
-			iRet = RS_RET_OUT_OF_MEMORY;
+		char *sys_pid;
+
+		CHKiRet_Hdlr(sanitizeValue(((const char *)pidget) + 11, pidlength - 11, &sys_pid)) {
 			free (sys_iden);
-			goto free_message;
+			FINALIZE;
 		}
-	} else {
-		sys_pid = NULL;
-	}
-
-	if (sys_pid) {
 		r = asprintf(&sys_iden_help, "%s[%s]:", sys_iden, sys_pid);
+		free (sys_pid);
 	} else {
 		r = asprintf(&sys_iden_help, "%s:", sys_iden);
 	}
 
 	free (sys_iden);
-	free (sys_pid);
 
 	if (-1 == r) {
-		iRet = RS_RET_OUT_OF_MEMORY;
-		goto finalize_it;
+		ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
 	}
 
 	json = json_object_new_object();
 
 	SD_JOURNAL_FOREACH_DATA(j, get, l) {
+		char *data;
+		char *name;
+
 		/* locate equal sign, this is always present */
 		equal_sign = memchr(get, '=', l);
 
@@ -372,18 +383,13 @@ readjournal() {
 			break;
 		}
 
-		if (name == NULL) {
-			iRet = RS_RET_OUT_OF_MEMORY;
-			goto ret;
-		}
+		CHKmalloc(name);
 
 		prefixlen++; /* remove '=' */
 
-		data = strndup(get + prefixlen, l - prefixlen);
-		if (data == NULL) {
-			iRet = RS_RET_OUT_OF_MEMORY;
+		CHKiRet_Hdlr(sanitizeValue(((const char *)get) + prefixlen, l - prefixlen, &data)) {
 			free (name);
-			goto ret;
+			FINALIZE;
 		}
 
 		/* and save them to json object */
@@ -403,10 +409,10 @@ readjournal() {
 	enqMsg((uchar *)message, (uchar *) sys_iden_help, facility, severity, &tv, json);
 
 finalize_it:
-	free(sys_iden_help);
-free_message:
-	free(message);
-ret:
+	if (sys_iden_help != NULL)
+		free(sys_iden_help);
+	if (message != NULL)
+		free(message);
 	RETiRet;
 }
 
-- 
1.9.3