summaryrefslogtreecommitdiff
path: root/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'dir.c')
-rw-r--r--dir.c79
1 files changed, 75 insertions, 4 deletions
diff --git a/dir.c b/dir.c
index b460211..014741d 100644
--- a/dir.c
+++ b/dir.c
@@ -636,11 +636,42 @@ int pl_hashmap_cmp(const void *unused_cmp_data,
return strncmp(ee1->pattern, ee2->pattern, min_len);
}
+static char *dup_and_filter_pattern(const char *pattern)
+{
+ char *set, *read;
+ size_t count = 0;
+ char *result = xstrdup(pattern);
+
+ set = result;
+ read = result;
+
+ while (*read) {
+ /* skip escape characters (once) */
+ if (*read == '\\')
+ read++;
+
+ *set = *read;
+
+ set++;
+ read++;
+ count++;
+ }
+ *set = 0;
+
+ if (count > 2 &&
+ *(set - 1) == '*' &&
+ *(set - 2) == '/')
+ *(set - 2) = 0;
+
+ return result;
+}
+
static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern *given)
{
struct pattern_entry *translated;
char *truncated;
char *data = NULL;
+ const char *prev, *cur, *next;
if (!pl->use_cone_patterns)
return;
@@ -657,17 +688,57 @@ static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern
return;
}
+ if (given->patternlen <= 2 ||
+ *given->pattern == '*' ||
+ strstr(given->pattern, "**")) {
+ /* Not a cone pattern. */
+ warning(_("unrecognized pattern: '%s'"), given->pattern);
+ goto clear_hashmaps;
+ }
+
+ prev = given->pattern;
+ cur = given->pattern + 1;
+ next = given->pattern + 2;
+
+ while (*cur) {
+ /* Watch for glob characters '*', '\', '[', '?' */
+ if (!is_glob_special(*cur))
+ goto increment;
+
+ /* But only if *prev != '\\' */
+ if (*prev == '\\')
+ goto increment;
+
+ /* But allow the initial '\' */
+ if (*cur == '\\' &&
+ is_glob_special(*next))
+ goto increment;
+
+ /* But a trailing '/' then '*' is fine */
+ if (*prev == '/' &&
+ *cur == '*' &&
+ *next == 0)
+ goto increment;
+
+ /* Not a cone pattern. */
+ warning(_("unrecognized pattern: '%s'"), given->pattern);
+ goto clear_hashmaps;
+
+ increment:
+ prev++;
+ cur++;
+ next++;
+ }
+
if (given->patternlen > 2 &&
!strcmp(given->pattern + given->patternlen - 2, "/*")) {
if (!(given->flags & PATTERN_FLAG_NEGATIVE)) {
/* Not a cone pattern. */
- pl->use_cone_patterns = 0;
warning(_("unrecognized pattern: '%s'"), given->pattern);
goto clear_hashmaps;
}
- truncated = xstrdup(given->pattern);
- truncated[given->patternlen - 2] = 0;
+ truncated = dup_and_filter_pattern(given->pattern);
translated = xmalloc(sizeof(struct pattern_entry));
translated->pattern = truncated;
@@ -701,7 +772,7 @@ static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern
translated = xmalloc(sizeof(struct pattern_entry));
- translated->pattern = xstrdup(given->pattern);
+ translated->pattern = dup_and_filter_pattern(given->pattern);
translated->patternlen = given->patternlen;
hashmap_entry_init(&translated->ent,
ignore_case ?