From 361adbf9e520d695ae13efe6084cbcdebe4779e2 Mon Sep 17 00:00:00 2001 From: Dominic Cleal Date: Tue, 19 Nov 2013 09:39:23 +0000 Subject: [PATCH] * src/transform.c (filter_matches): wrap fnmatch to ensure that an incl pattern containing "//" matches file paths Fixes RHBZ#1031084 --- src/transform.c | 38 ++++++++++++++++++++++++++++++++++---- tests/test-save.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/src/transform.c b/src/transform.c index 1ee8da8..ccbe422 100644 --- a/src/transform.c +++ b/src/transform.c @@ -142,6 +142,33 @@ static char *mtime_as_string(struct augeas *aug, const char *fname) { return NULL; } +/* fnmatch(3) which will match // in a pattern to a path, like glob(3) does */ +static int fnmatch_normalize(const char *pattern, const char *string, int flags) { + int i, j, r; + char *pattern_norm = NULL; + + r = ALLOC_N(pattern_norm, strlen(pattern) + 1); + if (r < 0) + goto error; + + for (i = 0, j = 0; i < strlen(pattern); i++) { + if (pattern[i] != '/' || pattern[i+1] != '/') { + pattern_norm[j] = pattern[i]; + j++; + } + } + pattern_norm[j] = 0; + + r = fnmatch(pattern_norm, string, flags); + FREE(pattern_norm); + return r; + + error: + if (pattern_norm != NULL) + FREE(pattern_norm); + return -1; +} + static bool file_current(struct augeas *aug, const char *fname, struct tree *finfo) { struct tree *mtime = tree_child(finfo, s_mtime); @@ -217,9 +244,12 @@ static int filter_generate(struct tree *xfm, const char *root, if (strchr(e->value, SEP) == NULL) path = pathbase(path); - if ((r = fnmatch(e->value, path, fnm_flags)) == 0) { + + r = fnmatch_normalize(e->value, path, fnm_flags); + if (r < 0) + goto error; + else if (r == 0) include = false; - } } if (include) @@ -254,7 +284,7 @@ static int filter_generate(struct tree *xfm, const char *root, static int filter_matches(struct tree *xfm, const char *path) { int found = 0; list_for_each(f, xfm->children) { - if (is_incl(f) && fnmatch(f->value, path, fnm_flags) == 0) { + if (is_incl(f) && fnmatch_normalize(f->value, path, fnm_flags) == 0) { found = 1; break; } @@ -262,7 +292,7 @@ static int filter_matches(struct tree *xfm, const char *path) { if (! found) return 0; list_for_each(f, xfm->children) { - if (is_excl(f) && (fnmatch(f->value, path, fnm_flags) == 0)) + if (is_excl(f) && (fnmatch_normalize(f->value, path, fnm_flags) == 0)) return 0; } return 1; diff --git a/tests/test-save.c b/tests/test-save.c index 04b86f7..617ef31 100644 --- a/tests/test-save.c +++ b/tests/test-save.c @@ -183,6 +183,44 @@ static void testRelPath(CuTest *tc) { CuAssertIntEquals(tc, 1, r); } +/* Check that loading and saving a file with // in the incl pattern works. + * RHBZ#1031084 + */ +static void testDoubleSlashPath(CuTest *tc) { + int r; + + r = aug_rm(aug, "/augeas/load/*"); + CuAssertPositive(tc, r); + + r = aug_set(aug, "/augeas/load/Hosts/lens", "Hosts.lns"); + CuAssertRetSuccess(tc, r); + r = aug_set(aug, "/augeas/load/Hosts/incl", "/etc//hosts"); + CuAssertRetSuccess(tc, r); + r = aug_load(aug); + CuAssertRetSuccess(tc, r); + + r = aug_match(aug, "/files/etc/hosts/1/alias[ . = 'new']", NULL); + CuAssertIntEquals(tc, 0, r); + + r = aug_set(aug, "/files/etc/hosts/1/alias[last() + 1]", "new"); + CuAssertRetSuccess(tc, r); + + r = aug_save(aug); + CuAssertRetSuccess(tc, r); + r = aug_match(aug, "/augeas//error", NULL); + CuAssertIntEquals(tc, 0, r); + + /* Force reloading the file */ + r = aug_rm(aug, "/augeas/files//mtime"); + CuAssertPositive(tc, r); + + r = aug_load(aug); + CuAssertRetSuccess(tc, r); + + r = aug_match(aug, "/files/etc/hosts/1/alias[. = 'new']", NULL); + CuAssertIntEquals(tc, 1, r); +} + int main(void) { char *output = NULL; CuSuite* suite = CuSuiteNew(); @@ -206,6 +244,7 @@ int main(void) { SUITE_ADD_TEST(suite, testMultipleXfm); SUITE_ADD_TEST(suite, testMtime); SUITE_ADD_TEST(suite, testRelPath); + SUITE_ADD_TEST(suite, testDoubleSlashPath); CuSuiteRun(suite); CuSuiteSummary(suite, &output); -- 1.8.3.1