blob: 9b3bf136db76e71e8e09e1cf5344e759128b89d0 [file] [log] [blame]
From 3a9bf982abae5aa8729b092e845f4283ec498dca Mon Sep 17 00:00:00 2001
From: Tim Song <tengs@chromium.org>
Date: Tue, 14 May 2013 14:32:38 -0700
Subject: [PATCH] Patch dbus-send to support escaping commas in string elements
of arrays.
BUG=chromium:240540
TEST=Telemetry tests on cros pass with escaped commas in arguments.
Change-Id: I1a284dfa443f2048dddaa85912b518224aaea5d5
Reviewed-on: https://gerrit.chromium.org/gerrit/51185
Reviewed-by: Elly Jones <ellyjones@chromium.org>
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
Tested-by: Tim Song <tengs@chromium.org>
Commit-Queue: Tim Song <tengs@chromium.org>
---
tools/dbus-send.c | 78 ++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 70 insertions(+), 8 deletions(-)
diff --git a/tools/dbus-send.c b/tools/dbus-send.c
index a1884837..52623a52 100644
--- a/tools/dbus-send.c
+++ b/tools/dbus-send.c
@@ -159,21 +159,83 @@ append_arg (DBusMessageIter *iter, int type, const char *value)
handle_oom (ret);
}
+// Note: buffer must be pre-allocated and at least as big as str.
+static int
+get_next_token (const char *str, int loc, char *buffer)
+{
+ int str_index, buffer_index = 0;
+
+ enum State {START, ESCAPE};
+ enum State state = START;
+
+ for (str_index = loc; str[str_index] != '\0'; str_index++)
+ {
+ if (state == START)
+ {
+ switch (str[str_index])
+ {
+ case '\\':
+ state = ESCAPE;
+ continue;
+
+ // If we hit a , in the start state, we should treat it as
+ // an argument separator since it's not escaped.
+ case ',':
+ buffer[buffer_index] = '\0';
+ return str_index + 1;
+ }
+ }
+ else if (state == ESCAPE)
+ {
+ // If the \ doesn't immediately precede a , or another \, then
+ // it's not being used as an escape character.
+ // Similarly, if we have a string of multiple \s as the last
+ // characters, then they're also not being used as escape characters.
+ if ((str[str_index] != ',' && str[str_index] != '\\') ||
+ (str[str_index] == '\\' && str[str_index + 1] == '\0'))
+ {
+ buffer[buffer_index] = '\\';
+ buffer_index++;
+ }
+
+ state = START;
+ }
+
+ buffer[buffer_index] = str[str_index];
+ buffer_index++;
+ }
+
+ // If we end on a single \, then it's not being used as an escape character.
+ // Note the earlier check will only catch if we end on a string of multiple
+ // \s.
+ if (state == ESCAPE)
+ {
+ buffer[buffer_index] = '\\';
+ buffer_index++;
+ }
+ buffer[buffer_index] = '\0';
+
+ return -1;
+}
+
static void
append_array (DBusMessageIter *iter, int type, const char *value)
{
- const char *val;
- char *dupval = strdup (value);
+ char *buffer = strdup (value);
- handle_oom (dupval != NULL);
+ handle_oom (buffer != NULL);
- val = strtok (dupval, ",");
- while (val != NULL)
+ int loc = 0;
+ while (loc >= 0)
{
- append_arg (iter, type, val);
- val = strtok (NULL, ",");
+ loc = get_next_token (value, loc, buffer);
+
+ // We don't want to include empty strings, even if there are
+ // several commas directly beside each other.
+ if (buffer[0] != '\0')
+ append_arg (iter, type, buffer);
}
- free (dupval);
+ free (buffer);
}
static void
--
2.30.1