[PATCH 2/3] vfs_snapper: add DBus string encoding and decoding helpers

David Disseldorp ddiss at samba.org
Wed Jan 21 10:16:56 MST 2015


Snapper uses the following mechanism for encoding and decoding strings
used in DBus traffic:
Characters above 127 (0x7F - ASCII DEL) must be encoded hexadecimal as
"\x??". As a consequence "\" must be encoded as "\\".

This change adds string encoding and decoding helpers to vfs_snapper.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=11055

Signed-off-by: David Disseldorp <ddiss at samba.org>
---
 source3/modules/vfs_snapper.c | 124 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git a/source3/modules/vfs_snapper.c b/source3/modules/vfs_snapper.c
index ed6e073..35f2a82 100644
--- a/source3/modules/vfs_snapper.c
+++ b/source3/modules/vfs_snapper.c
@@ -91,6 +91,130 @@ static NTSTATUS snapper_err_ntstatus_map(const char *snapper_err_str)
 	return NT_STATUS_UNSUCCESSFUL;
 }
 
+/*
+ * Strings are UTF-8. Other characters must be encoded hexadecimal as "\x??".
+ * As a consequence "\" must be encoded as "\\".
+ */
+static NTSTATUS snapper_dbus_str_encode(TALLOC_CTX *mem_ctx, const char *in_str,
+					char **_out_str)
+{
+	size_t in_len;
+	char *out_str;
+	int i;
+	int out_off;
+	int out_len;
+
+	if (in_str == NULL) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	in_len = strlen(in_str);
+
+	/* output can be max 4 times the length of @in_str, +1 for terminator */
+	out_len = (in_len * 4) + 1;
+
+	out_str = talloc_array(mem_ctx, char, out_len);
+	if (out_str == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	out_off = 0;
+	for (i = 0; i < in_len; i++) {
+		size_t pushed;
+
+		if (in_str[i] == '\\') {
+			pushed = snprintf(out_str + out_off, out_len - out_off,
+					  "\\\\");
+		} else if ((unsigned char)in_str[i] > 127) {
+			pushed = snprintf(out_str + out_off, out_len - out_off,
+					  "\\x%02x", (unsigned char)in_str[i]);
+		} else {
+			/* regular character */
+			*(out_str + out_off) = in_str[i];
+			pushed = sizeof(char);
+		}
+		if (pushed >= out_len - out_off) {
+			/* truncated, should never happen */
+			talloc_free(out_str);
+			return NT_STATUS_INTERNAL_ERROR;
+		}
+		out_off += pushed;
+	}
+
+	*(out_str + out_off) = '\0';
+	*_out_str = out_str;
+
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS snapper_dbus_str_decode(TALLOC_CTX *mem_ctx, const char *in_str,
+					char **_out_str)
+{
+	size_t in_len;
+	char *out_str;
+	int i;
+	int out_off;
+	int out_len;
+
+	if (in_str == NULL) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	in_len = strlen(in_str);
+
+	/* output cannot be larger than input, +1 for terminator */
+	out_len = in_len + 1;
+
+	out_str = talloc_array(mem_ctx, char, out_len);
+	if (out_str == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	out_off = 0;
+	for (i = 0; i < in_len; i++) {
+		int j;
+		char hex_buf[3];
+		unsigned int non_ascii_byte;
+
+		if (in_str[i] != '\\') {
+			out_str[out_off] = in_str[i];
+			out_off++;
+			continue;
+		}
+
+		i++;
+		if (in_str[i] == '\\') {
+			out_str[out_off] = '\\';
+			out_off++;
+			continue;
+		} else if (in_str[i] != 'x') {
+			goto err_invalid_src_encoding;
+		}
+
+		/* non-ASCII, encoded as two hex chars */
+		for (j = 0; j < 2; j++) {
+			i++;
+			if ((in_str[i] == '\0') || !isxdigit(in_str[i])) {
+				goto err_invalid_src_encoding;
+			}
+			hex_buf[j] = in_str[i];
+		}
+		hex_buf[2] = '\0';
+
+		sscanf(hex_buf, "%x", &non_ascii_byte);
+		out_str[out_off] = (unsigned char)non_ascii_byte;
+		out_off++;
+	}
+
+	out_str[out_off] = '\0';
+	*_out_str = out_str;
+
+	return NT_STATUS_OK;
+err_invalid_src_encoding:
+	DEBUG(0, ("invalid encoding %s\n", in_str));
+	return NT_STATUS_INVALID_PARAMETER;
+}
+
 static DBusConnection *snapper_dbus_conn_create(void)
 {
 	DBusError err;
-- 
2.1.2



More information about the samba-technical mailing list