]> git.ipfire.org Git - thirdparty/git.git/blobdiff - dir.c
The 19th batch
[thirdparty/git.git] / dir.c
diff --git a/dir.c b/dir.c
index 20ebe4cba2687e027765876ddc57b086fa85dd71..5a23376bdaec3a7811677e7ca83e76ababa60a52 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -5,6 +5,9 @@
  * Copyright (C) Linus Torvalds, 2005-2006
  *              Junio Hamano, 2005-2006
  */
  * Copyright (C) Linus Torvalds, 2005-2006
  *              Junio Hamano, 2005-2006
  */
+
+#define USE_THE_REPOSITORY_VARIABLE
+
 #include "git-compat-util.h"
 #include "abspath.h"
 #include "config.h"
 #include "git-compat-util.h"
 #include "abspath.h"
 #include "config.h"
 #include "symlinks.h"
 #include "trace2.h"
 #include "tree.h"
 #include "symlinks.h"
 #include "trace2.h"
 #include "tree.h"
+#include "hex.h"
+
+ /*
+  * The maximum size of a pattern/exclude file. If the file exceeds this size
+  * we will ignore it.
+  */
+#define PATTERN_MAX_FILE_SIZE (100 * 1024 * 1024)
 
 /*
  * Tells read_directory_recursive how a file or directory should be treated.
 
 /*
  * Tells read_directory_recursive how a file or directory should be treated.
@@ -85,7 +95,7 @@ int count_slashes(const char *s)
        return cnt;
 }
 
        return cnt;
 }
 
-int fspathcmp(const char *a, const char *b)
+int git_fspathcmp(const char *a, const char *b)
 {
        return ignore_case ? strcasecmp(a, b) : strcmp(a, b);
 }
 {
        return ignore_case ? strcasecmp(a, b) : strcmp(a, b);
 }
@@ -95,11 +105,23 @@ int fspatheq(const char *a, const char *b)
        return !fspathcmp(a, b);
 }
 
        return !fspathcmp(a, b);
 }
 
-int fspathncmp(const char *a, const char *b, size_t count)
+int git_fspathncmp(const char *a, const char *b, size_t count)
 {
        return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count);
 }
 
 {
        return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count);
 }
 
+int paths_collide(const char *a, const char *b)
+{
+       size_t len_a = strlen(a), len_b = strlen(b);
+
+       if (len_a == len_b)
+               return fspatheq(a, b);
+
+       if (len_a < len_b)
+               return is_dir_sep(b[len_a]) && !fspathncmp(a, b, len_a);
+       return is_dir_sep(a[len_b]) && !fspathncmp(a, b, len_b);
+}
+
 unsigned int fspathhash(const char *str)
 {
        return ignore_case ? strihash(str) : strhash(str);
 unsigned int fspathhash(const char *str)
 {
        return ignore_case ? strihash(str) : strhash(str);
@@ -714,6 +736,17 @@ static char *dup_and_filter_pattern(const char *pattern)
        return result;
 }
 
        return result;
 }
 
+static void clear_pattern_entry_hashmap(struct hashmap *map)
+{
+       struct hashmap_iter iter;
+       struct pattern_entry *entry;
+
+       hashmap_for_each_entry(map, &iter, entry, ent) {
+               free(entry->pattern);
+       }
+       hashmap_clear_and_free(map, struct pattern_entry, ent);
+}
+
 static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern *given)
 {
        struct pattern_entry *translated;
 static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern *given)
 {
        struct pattern_entry *translated;
@@ -787,6 +820,8 @@ static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern
 
        if (given->patternlen > 2 &&
            !strcmp(given->pattern + given->patternlen - 2, "/*")) {
 
        if (given->patternlen > 2 &&
            !strcmp(given->pattern + given->patternlen - 2, "/*")) {
+               struct pattern_entry *old;
+
                if (!(given->flags & PATTERN_FLAG_NEGATIVE)) {
                        /* Not a cone pattern. */
                        warning(_("unrecognized pattern: '%s'"), given->pattern);
                if (!(given->flags & PATTERN_FLAG_NEGATIVE)) {
                        /* Not a cone pattern. */
                        warning(_("unrecognized pattern: '%s'"), given->pattern);
@@ -812,7 +847,11 @@ static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern
                }
 
                hashmap_add(&pl->parent_hashmap, &translated->ent);
                }
 
                hashmap_add(&pl->parent_hashmap, &translated->ent);
-               hashmap_remove(&pl->recursive_hashmap, &translated->ent, &data);
+               old = hashmap_remove_entry(&pl->recursive_hashmap, translated, ent, &data);
+               if (old) {
+                       free(old->pattern);
+                       free(old);
+               }
                free(data);
                return;
        }
                free(data);
                return;
        }
@@ -843,8 +882,8 @@ static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern
 
 clear_hashmaps:
        warning(_("disabling cone pattern matching"));
 
 clear_hashmaps:
        warning(_("disabling cone pattern matching"));
-       hashmap_clear_and_free(&pl->parent_hashmap, struct pattern_entry, ent);
-       hashmap_clear_and_free(&pl->recursive_hashmap, struct pattern_entry, ent);
+       clear_pattern_entry_hashmap(&pl->recursive_hashmap);
+       clear_pattern_entry_hashmap(&pl->parent_hashmap);
        pl->use_cone_patterns = 0;
 }
 
        pl->use_cone_patterns = 0;
 }
 
@@ -896,12 +935,7 @@ void add_pattern(const char *string, const char *base,
        int nowildcardlen;
 
        parse_path_pattern(&string, &patternlen, &flags, &nowildcardlen);
        int nowildcardlen;
 
        parse_path_pattern(&string, &patternlen, &flags, &nowildcardlen);
-       if (flags & PATTERN_FLAG_MUSTBEDIR) {
-               FLEXPTR_ALLOC_MEM(pattern, pattern, string, patternlen);
-       } else {
-               pattern = xmalloc(sizeof(*pattern));
-               pattern->pattern = string;
-       }
+       FLEX_ALLOC_MEM(pattern, pattern, string, patternlen);
        pattern->patternlen = patternlen;
        pattern->nowildcardlen = nowildcardlen;
        pattern->base = base;
        pattern->patternlen = patternlen;
        pattern->nowildcardlen = nowildcardlen;
        pattern->base = base;
@@ -943,9 +977,8 @@ void clear_pattern_list(struct pattern_list *pl)
        for (i = 0; i < pl->nr; i++)
                free(pl->patterns[i]);
        free(pl->patterns);
        for (i = 0; i < pl->nr; i++)
                free(pl->patterns[i]);
        free(pl->patterns);
-       free(pl->filebuf);
-       hashmap_clear_and_free(&pl->recursive_hashmap, struct pattern_entry, ent);
-       hashmap_clear_and_free(&pl->parent_hashmap, struct pattern_entry, ent);
+       clear_pattern_entry_hashmap(&pl->recursive_hashmap);
+       clear_pattern_entry_hashmap(&pl->parent_hashmap);
 
        memset(pl, 0, sizeof(*pl));
 }
 
        memset(pl, 0, sizeof(*pl));
 }
@@ -1136,7 +1169,14 @@ static int add_patterns(const char *fname, const char *base, int baselen,
                }
        }
 
                }
        }
 
+       if (size > PATTERN_MAX_FILE_SIZE) {
+               warning("ignoring excessively large pattern file: %s", fname);
+               free(buf);
+               return -1;
+       }
+
        add_patterns_from_buffer(buf, size, base, baselen, pl);
        add_patterns_from_buffer(buf, size, base, baselen, pl);
+       free(buf);
        return 0;
 }
 
        return 0;
 }
 
@@ -1144,16 +1184,15 @@ static int add_patterns_from_buffer(char *buf, size_t size,
                                    const char *base, int baselen,
                                    struct pattern_list *pl)
 {
                                    const char *base, int baselen,
                                    struct pattern_list *pl)
 {
+       char *orig = buf;
        int i, lineno = 1;
        char *entry;
 
        hashmap_init(&pl->recursive_hashmap, pl_hashmap_cmp, NULL, 0);
        hashmap_init(&pl->parent_hashmap, pl_hashmap_cmp, NULL, 0);
 
        int i, lineno = 1;
        char *entry;
 
        hashmap_init(&pl->recursive_hashmap, pl_hashmap_cmp, NULL, 0);
        hashmap_init(&pl->parent_hashmap, pl_hashmap_cmp, NULL, 0);
 
-       pl->filebuf = buf;
-
        if (skip_utf8_bom(&buf, size))
        if (skip_utf8_bom(&buf, size))
-               size -= buf - pl->filebuf;
+               size -= buf - orig;
 
        entry = buf;
 
 
        entry = buf;
 
@@ -1192,7 +1231,15 @@ int add_patterns_from_blob_to_list(
        if (r != 1)
                return r;
 
        if (r != 1)
                return r;
 
+       if (size > PATTERN_MAX_FILE_SIZE) {
+               warning("ignoring excessively large pattern blob: %s",
+                       oid_to_hex(oid));
+               free(buf);
+               return -1;
+       }
+
        add_patterns_from_buffer(buf, size, base, baselen, pl);
        add_patterns_from_buffer(buf, size, base, baselen, pl);
+       free(buf);
        return 0;
 }
 
        return 0;
 }
 
@@ -1643,7 +1690,7 @@ static void prep_exclude(struct dir_struct *dir,
                }
 
                /* Try to read per-directory file */
                }
 
                /* Try to read per-directory file */
-               oidclr(&oid_stat.oid);
+               oidclr(&oid_stat.oid, the_repository->hash_algo);
                oid_stat.valid = 0;
                if (dir->exclude_per_dir &&
                    /*
                oid_stat.valid = 0;
                if (dir->exclude_per_dir &&
                    /*
@@ -3306,7 +3353,8 @@ static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)
        struct object_id submodule_head;
 
        if ((flag & REMOVE_DIR_KEEP_NESTED_GIT) &&
        struct object_id submodule_head;
 
        if ((flag & REMOVE_DIR_KEEP_NESTED_GIT) &&
-           !resolve_gitlink_ref(path->buf, "HEAD", &submodule_head)) {
+           !repo_resolve_gitlink_ref(the_repository, path->buf,
+                                     "HEAD", &submodule_head)) {
                /* Do not descend and nuke a nested git work tree. */
                if (kept_up)
                        *kept_up = 1;
                /* Do not descend and nuke a nested git work tree. */
                if (kept_up)
                        *kept_up = 1;
@@ -3749,7 +3797,7 @@ static void read_oid(size_t pos, void *cb)
                rd->data = rd->end + 1;
                return;
        }
                rd->data = rd->end + 1;
                return;
        }
-       oidread(&ud->exclude_oid, rd->data);
+       oidread(&ud->exclude_oid, rd->data, the_repository->hash_algo);
        rd->data += the_hash_algo->rawsz;
 }
 
        rd->data += the_hash_algo->rawsz;
 }
 
@@ -3757,7 +3805,7 @@ static void load_oid_stat(struct oid_stat *oid_stat, const unsigned char *data,
                          const unsigned char *sha1)
 {
        stat_data_from_disk(&oid_stat->stat, data);
                          const unsigned char *sha1)
 {
        stat_data_from_disk(&oid_stat->stat, data);
-       oidread(&oid_stat->oid, sha1);
+       oidread(&oid_stat->oid, sha1, the_repository->hash_algo);
        oid_stat->valid = 1;
 }
 
        oid_stat->valid = 1;
 }