From d4c15d2c386f355a4b8823bdd72f776c46ba9c1d Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Thu, 17 Mar 2016 14:25:18 +0100 Subject: [PATCH] Ignores: expand escapes #4568 (cherry picked from commit d7bd1300a8397c2782e8d75cf7c595b1ada70d88) --- csync/src/csync_exclude.c | 43 ++++++++++++++++++- csync/tests/csync_tests/check_csync_exclude.c | 20 +++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/csync/src/csync_exclude.c b/csync/src/csync_exclude.c index 375425106..49649464d 100644 --- a/csync/src/csync_exclude.c +++ b/csync/src/csync_exclude.c @@ -47,6 +47,43 @@ int _csync_exclude_add(c_strlist_t **inList, const char *string) { return c_strlist_add_grow(inList, string); } +/** Expands C-like escape sequences. + * + * The returned string is heap-allocated and owned by the caller. + */ +static const char *csync_exclude_expand_escapes(const char * input) +{ + size_t i_len = strlen(input) + 1; + char *out = c_malloc(i_len); // out can only be shorter + + for (size_t i = 0, o = 0; i < i_len; ++i) { + if (input[i] == '\\') { + // at worst input[i+1] is \0 + switch (input[i+1]) { + case '\'': out[o++] = '\''; break; + case '"': out[o++] = '"'; break; + case '?': out[o++] = '?'; break; + case '\\': out[o++] = '\\'; break; + case 'a': out[o++] = '\a'; break; + case 'b': out[o++] = '\b'; break; + case 'f': out[o++] = '\f'; break; + case 'n': out[o++] = '\n'; break; + case 'r': out[o++] = '\r'; break; + case 't': out[o++] = '\t'; break; + case 'v': out[o++] = '\v'; break; + default: + out[o++] = input[i]; + out[o++] = input[i+1]; + break; + } + ++i; + } else { + out[o++] = input[i]; + } + } + return out; +} + int csync_exclude_load(const char *fname, c_strlist_t **list) { int fd = -1; int i = 0; @@ -99,8 +136,10 @@ int csync_exclude_load(const char *fname, c_strlist_t **list) { if (entry != buf + i) { buf[i] = '\0'; if (*entry != '#') { - CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Adding entry: %s", entry); - rc = _csync_exclude_add(list, entry); + const char *unescaped = csync_exclude_expand_escapes(entry); + CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Adding entry: %s", unescaped); + rc = _csync_exclude_add(list, unescaped); + SAFE_FREE(unescaped); if (rc < 0) { goto out; } diff --git a/csync/tests/csync_tests/check_csync_exclude.c b/csync/tests/csync_tests/check_csync_exclude.c index 56a497ea6..3c9fe256e 100644 --- a/csync/tests/csync_tests/check_csync_exclude.c +++ b/csync/tests/csync_tests/check_csync_exclude.c @@ -346,6 +346,25 @@ static void check_csync_excluded_performance(void **state) } } +static void check_csync_exclude_expand_escapes(void **state) +{ + (void)state; + + const char *str = csync_exclude_expand_escapes( + "keep \\' \\\" \\? \\\\ \\a \\b \\f \\n \\r \\t \\v \\z"); + assert_true(0 == strcmp( + str, "keep ' \" ? \\ \a \b \f \n \r \t \v \\z")); + SAFE_FREE(str); + + str = csync_exclude_expand_escapes(""); + assert_true(0 == strcmp(str, "")); + SAFE_FREE(str); + + str = csync_exclude_expand_escapes("\\"); + assert_true(0 == strcmp(str, "\\")); + SAFE_FREE(str); +} + int torture_run_tests(void) { const UnitTest tests[] = { @@ -356,6 +375,7 @@ int torture_run_tests(void) unit_test_setup_teardown(check_csync_pathes, setup_init, teardown), unit_test_setup_teardown(check_csync_is_windows_reserved_word, setup_init, teardown), unit_test_setup_teardown(check_csync_excluded_performance, setup_init, teardown), + unit_test(check_csync_exclude_expand_escapes), }; return run_tests(tests);