diff options
author | Lennart Poettering <lennart@poettering.net> | 2013-03-05 19:58:32 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2013-03-05 20:05:46 +0100 |
commit | d47c78be4a2acbb631a26af11b7ce2ef57f55996 (patch) | |
tree | 024967d8250f9dea111ca82dff3b45a4c0b81573 | |
parent | 2f2343c6b15ec5495eb5032ae36b937fe36177cc (diff) |
util: properly escape corner cases in bus_path_escape(), too
This follows the suggestions from:
http://lists.freedesktop.org/archives/systemd-devel/2013-March/009363.html
-rw-r--r-- | src/shared/util.c | 21 | ||||
-rw-r--r-- | src/test/test-util.c | 24 |
2 files changed, 41 insertions, 4 deletions
diff --git a/src/shared/util.c b/src/shared/util.c index e643cd367c..b7ba7fbe84 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -1325,16 +1325,24 @@ char *bus_path_escape(const char *s) { assert(s); /* Escapes all chars that D-Bus' object path cannot deal - * with. Can be reverse with bus_path_unescape() */ + * with. Can be reverse with bus_path_unescape(). We special + * case the empty string. */ - if (!(r = new(char, strlen(s)*3+1))) + if (*s == 0) + return strdup("_"); + + r = new(char, strlen(s)*3 + 1); + if (!r) return NULL; for (f = s, t = r; *f; f++) { + /* Escape everything that is not a-zA-Z0-9. We also + * escape 0-9 if it's the first character */ + if (!(*f >= 'A' && *f <= 'Z') && !(*f >= 'a' && *f <= 'z') && - !(*f >= '0' && *f <= '9')) { + !(f > s && *f >= '0' && *f <= '9')) { *(t++) = '_'; *(t++) = hexchar(*f >> 4); *(t++) = hexchar(*f); @@ -1352,7 +1360,12 @@ char *bus_path_unescape(const char *f) { assert(f); - if (!(r = strdup(f))) + /* Special case for the empty string */ + if (streq(f, "_")) + return strdup(""); + + r = new(char, strlen(f) + 1); + if (!r) return NULL; for (t = r; *f; f++) { diff --git a/src/test/test-util.c b/src/test/test-util.c index cb0af4f6a1..789fc089fe 100644 --- a/src/test/test-util.c +++ b/src/test/test-util.c @@ -261,6 +261,29 @@ static void test_memdup_multiply(void) { free(dup); } +static void test_bus_path_escape_one(const char *a, const char *b) { + _cleanup_free_ char *t = NULL, *x = NULL, *y = NULL; + + assert_se(t = bus_path_escape(a)); + assert_se(streq(t, b)); + + assert_se(x = bus_path_unescape(t)); + assert_se(streq(a, x)); + + assert_se(y = bus_path_unescape(b)); + assert_se(streq(a, y)); +} + +static void test_bus_path_escape(void) { + test_bus_path_escape_one("foo123bar", "foo123bar"); + test_bus_path_escape_one("foo.bar", "foo_2ebar"); + test_bus_path_escape_one("foo_2ebar", "foo_5f2ebar"); + test_bus_path_escape_one("", "_"); + test_bus_path_escape_one("_", "_5f"); + test_bus_path_escape_one("1", "_31"); + test_bus_path_escape_one(":1", "_3a1"); +} + int main(int argc, char *argv[]) { test_streq_ptr(); test_first_word(); @@ -282,6 +305,7 @@ int main(int argc, char *argv[]) { test_foreach_word_quoted(); test_default_term_for_tty(); test_memdup_multiply(); + test_bus_path_escape(); return 0; } |