]> git.ipfire.org Git - thirdparty/git.git/commitdiff
tree-walk: store object_id in a separate member
authorbrian m. carlson <sandals@crustytoothpaste.net>
Tue, 15 Jan 2019 00:39:44 +0000 (00:39 +0000)
committerJunio C Hamano <gitster@pobox.com>
Tue, 15 Jan 2019 17:57:41 +0000 (09:57 -0800)
When parsing a tree, we read the object ID directly out of the tree
buffer. This is normally fine, but such an object ID cannot be used with
oidcpy, which copies GIT_MAX_RAWSZ bytes, because if we are using SHA-1,
there may not be that many bytes to copy.

Instead, store the object ID in a separate struct member. Since we can
no longer efficiently compute the path length, store that information as
well in struct name_entry. Ensure we only copy the object ID into the
new buffer if the path length is nonzero, as some callers will pass us
an empty path with no object ID following it, and we will not want to
read past the end of the buffer.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
19 files changed:
builtin/grep.c
builtin/merge-tree.c
builtin/pack-objects.c
builtin/reflog.c
cache-tree.c
delta-islands.c
fsck.c
http-push.c
list-objects.c
match-trees.c
notes.c
packfile.c
revision.c
tree-diff.c
tree-walk.c
tree-walk.h
tree.c
unpack-trees.c
walker.c

index bad9c0a3d5134a69d9388e169793b03c9952d9bf..6fb93c037031e7d32e1504247f3e7a677c51175d 100644 (file)
@@ -566,7 +566,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
                strbuf_add(base, entry.path, te_len);
 
                if (S_ISREG(entry.mode)) {
-                       hit |= grep_oid(opt, entry.oid, base->buf, tn_len,
+                       hit |= grep_oid(opt, &entry.oid, base->buf, tn_len,
                                         check_attr ? base->buf + tn_len : NULL);
                } else if (S_ISDIR(entry.mode)) {
                        enum object_type type;
@@ -574,10 +574,10 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
                        void *data;
                        unsigned long size;
 
-                       data = lock_and_read_oid_file(entry.oid, &type, &size);
+                       data = lock_and_read_oid_file(&entry.oid, &type, &size);
                        if (!data)
                                die(_("unable to read tree (%s)"),
-                                   oid_to_hex(entry.oid));
+                                   oid_to_hex(&entry.oid));
 
                        strbuf_addch(base, '/');
                        init_tree_desc(&sub, data, size);
@@ -585,7 +585,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
                                         check_attr, repo);
                        free(data);
                } else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
-                       hit |= grep_submodule(opt, repo, pathspec, entry.oid,
+                       hit |= grep_submodule(opt, repo, pathspec, &entry.oid,
                                              base->buf, base->buf + tn_len);
                }
 
index 70f6fc916765c5a5ca67c2dfe72e0480128182e3..4500c41e944022a0b525ea82ca2ea8fb8a17c722 100644 (file)
@@ -154,15 +154,15 @@ static void show_result(void)
 /* An empty entry never compares same, not even to another empty entry */
 static int same_entry(struct name_entry *a, struct name_entry *b)
 {
-       return  a->oid &&
-               b->oid &&
-               oideq(a->oid, b->oid) &&
+       return  !is_null_oid(&a->oid) &&
+               !is_null_oid(&b->oid) &&
+               oideq(&a->oid, &b->oid) &&
                a->mode == b->mode;
 }
 
 static int both_empty(struct name_entry *a, struct name_entry *b)
 {
-       return !(a->oid || b->oid);
+       return is_null_oid(&a->oid) && is_null_oid(&b->oid);
 }
 
 static struct merge_list *create_entry(unsigned stage, unsigned mode, const struct object_id *oid, const char *path)
@@ -178,7 +178,7 @@ static struct merge_list *create_entry(unsigned stage, unsigned mode, const stru
 
 static char *traverse_path(const struct traverse_info *info, const struct name_entry *n)
 {
-       char *path = xmallocz(traverse_path_len(info, n));
+       char *path = xmallocz(traverse_path_len(info, n) + the_hash_algo->rawsz);
        return make_traverse_path(path, info, n);
 }
 
@@ -192,8 +192,8 @@ static void resolve(const struct traverse_info *info, struct name_entry *ours, s
                return;
 
        path = traverse_path(info, result);
-       orig = create_entry(2, ours->mode, ours->oid, path);
-       final = create_entry(0, result->mode, result->oid, path);
+       orig = create_entry(2, ours->mode, &ours->oid, path);
+       final = create_entry(0, result->mode, &result->oid, path);
 
        final->link = orig;
 
@@ -217,7 +217,7 @@ static void unresolved_directory(const struct traverse_info *info,
 
        newbase = traverse_path(info, p);
 
-#define ENTRY_OID(e) (((e)->mode && S_ISDIR((e)->mode)) ? (e)->oid : NULL)
+#define ENTRY_OID(e) (((e)->mode && S_ISDIR((e)->mode)) ? &(e)->oid : NULL)
        buf0 = fill_tree_descriptor(t + 0, ENTRY_OID(n + 0));
        buf1 = fill_tree_descriptor(t + 1, ENTRY_OID(n + 1));
        buf2 = fill_tree_descriptor(t + 2, ENTRY_OID(n + 2));
@@ -243,7 +243,7 @@ static struct merge_list *link_entry(unsigned stage, const struct traverse_info
                path = entry->path;
        else
                path = traverse_path(info, n);
-       link = create_entry(stage, n->mode, n->oid, path);
+       link = create_entry(stage, n->mode, &n->oid, path);
        link->link = entry;
        return link;
 }
@@ -318,7 +318,7 @@ static int threeway_callback(int n, unsigned long mask, unsigned long dirmask, s
        }
 
        if (same_entry(entry+0, entry+1)) {
-               if (entry[2].oid && !S_ISDIR(entry[2].mode)) {
+               if (!is_null_oid(&entry[2].oid) && !S_ISDIR(entry[2].mode)) {
                        /* We did not touch, they modified -- take theirs */
                        resolve(info, entry+1, entry+2);
                        return mask;
index 24bba8147fc96ec2b124aa659c981af08e7a688d..327d9170c4daa15401e0dbe9627e211f0799af72 100644 (file)
@@ -1334,7 +1334,7 @@ static void add_pbase_object(struct tree_desc *tree,
                if (cmp < 0)
                        return;
                if (name[cmplen] != '/') {
-                       add_object_entry(entry.oid,
+                       add_object_entry(&entry.oid,
                                         object_type(entry.mode),
                                         fullname, 1);
                        return;
@@ -1345,7 +1345,7 @@ static void add_pbase_object(struct tree_desc *tree,
                        const char *down = name+cmplen+1;
                        int downlen = name_cmp_len(down);
 
-                       tree = pbase_tree_get(entry.oid);
+                       tree = pbase_tree_get(&entry.oid);
                        if (!tree)
                                return;
                        init_tree_desc(&sub, tree->tree_data, tree->tree_size);
index 64a8df4f252f598ff835c39ce8a3d3d417e8a31e..1f1010e2d9aec2b95487007ec30509fcbda605d6 100644 (file)
@@ -94,8 +94,8 @@ static int tree_is_complete(const struct object_id *oid)
        init_tree_desc(&desc, tree->buffer, tree->size);
        complete = 1;
        while (tree_entry(&desc, &entry)) {
-               if (!has_sha1_file(entry.oid->hash) ||
-                   (S_ISDIR(entry.mode) && !tree_is_complete(entry.oid))) {
+               if (!has_sha1_file(entry.oid.hash) ||
+                   (S_ISDIR(entry.mode) && !tree_is_complete(&entry.oid))) {
                        tree->object.flags |= INCOMPLETE;
                        complete = 0;
                }
index 190c6e5aa6bbc79f5267fa96e3c14ed2438c0488..98cb66587bff47db4180ea53dfae2238782a6687 100644 (file)
@@ -675,7 +675,7 @@ static void prime_cache_tree_rec(struct repository *r,
                        cnt++;
                else {
                        struct cache_tree_sub *sub;
-                       struct tree *subtree = lookup_tree(r, entry.oid);
+                       struct tree *subtree = lookup_tree(r, &entry.oid);
                        if (!subtree->object.parsed)
                                parse_tree(subtree);
                        sub = cache_tree_sub(it, entry.path);
@@ -724,7 +724,7 @@ int cache_tree_matches_traversal(struct cache_tree *root,
 
        it = find_cache_tree_from_traversal(root, info);
        it = cache_tree_find(it, ent->path);
-       if (it && it->entry_count > 0 && oideq(ent->oid, &it->oid))
+       if (it && it->entry_count > 0 && oideq(&ent->oid, &it->oid))
                return it->entry_count;
        return 0;
 }
index 191a930705480e044e816c2ba62afe039036eaf3..2186bd0738ed2fcbe216cf24a6c99ed4dc4ccd9b 100644 (file)
@@ -296,7 +296,7 @@ void resolve_tree_islands(struct repository *r,
                        if (S_ISGITLINK(entry.mode))
                                continue;
 
-                       obj = lookup_object(r, entry.oid->hash);
+                       obj = lookup_object(r, entry.oid.hash);
                        if (!obj)
                                continue;
 
diff --git a/fsck.c b/fsck.c
index 68502ce85b11bf0ef4445f2b1688b3834301ba53..2260adb71e7a9f1091d14bb635a4f082592b9512 100644 (file)
--- a/fsck.c
+++ b/fsck.c
@@ -410,14 +410,14 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op
                        continue;
 
                if (S_ISDIR(entry.mode)) {
-                       obj = (struct object *)lookup_tree(the_repository, entry.oid);
+                       obj = (struct object *)lookup_tree(the_repository, &entry.oid);
                        if (name && obj)
                                put_object_name(options, obj, "%s%s/", name,
                                        entry.path);
                        result = options->walk(obj, OBJ_TREE, data, options);
                }
                else if (S_ISREG(entry.mode) || S_ISLNK(entry.mode)) {
-                       obj = (struct object *)lookup_blob(the_repository, entry.oid);
+                       obj = (struct object *)lookup_blob(the_repository, &entry.oid);
                        if (name && obj)
                                put_object_name(options, obj, "%s%s", name,
                                        entry.path);
index cd485909127a79afcbb58ef18cd28977b65efb79..bb802d80ee08945b0008d8f6862e29c783410b35 100644 (file)
@@ -1311,11 +1311,11 @@ static struct object_list **process_tree(struct tree *tree,
        while (tree_entry(&desc, &entry))
                switch (object_type(entry.mode)) {
                case OBJ_TREE:
-                       p = process_tree(lookup_tree(the_repository, entry.oid),
+                       p = process_tree(lookup_tree(the_repository, &entry.oid),
                                         p);
                        break;
                case OBJ_BLOB:
-                       p = process_blob(lookup_blob(the_repository, entry.oid),
+                       p = process_blob(lookup_blob(the_repository, &entry.oid),
                                         p);
                        break;
                default:
index cf7f25bed352ac89625d311a1f5bdcd0c7a37878..ee6aff0cef7f9dd1bf1169f4f1c6dff0963886b7 100644 (file)
@@ -123,15 +123,15 @@ static void process_tree_contents(struct traversal_context *ctx,
                }
 
                if (S_ISDIR(entry.mode)) {
-                       struct tree *t = lookup_tree(ctx->revs->repo, entry.oid);
+                       struct tree *t = lookup_tree(ctx->revs->repo, &entry.oid);
                        t->object.flags |= NOT_USER_GIVEN;
                        process_tree(ctx, t, base, entry.path);
                }
                else if (S_ISGITLINK(entry.mode))
-                       process_gitlink(ctx, entry.oid->hash,
+                       process_gitlink(ctx, entry.oid.hash,
                                        base, entry.path);
                else {
-                       struct blob *b = lookup_blob(ctx->revs->repo, entry.oid);
+                       struct blob *b = lookup_blob(ctx->revs->repo, &entry.oid);
                        b->object.flags |= NOT_USER_GIVEN;
                        process_blob(ctx, b, base, entry.path);
                }
index c2b7329e0988e27bd4c121212a9f8c1011295021..18ab825bef57f3ea63f70adf9a5c4e4a4f000bc4 100644 (file)
@@ -106,7 +106,7 @@ static int score_trees(const struct object_id *hash1, const struct object_id *ha
                        update_tree_entry(&two);
                } else {
                        /* path appears in both */
-                       if (!oideq(one.entry.oid, two.entry.oid)) {
+                       if (!oideq(&one.entry.oid, &two.entry.oid)) {
                                /* they are different */
                                score += score_differs(one.entry.mode,
                                                       two.entry.mode,
diff --git a/notes.c b/notes.c
index 25cdce28b71a3ff15da424c8d1b1a89e28356dd5..7f7cc4d5112cd8f5098477d03034e8c8886dcb84 100644 (file)
--- a/notes.c
+++ b/notes.c
@@ -450,7 +450,7 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
 
                l = xcalloc(1, sizeof(*l));
                oidcpy(&l->key_oid, &object_oid);
-               oidcpy(&l->val_oid, entry.oid);
+               oidcpy(&l->val_oid, &entry.oid);
                if (note_tree_insert(t, node, n, l, type,
                                     combine_notes_concatenate))
                        die("Failed to load %s %s into notes tree "
@@ -481,7 +481,7 @@ handle_non_note:
                        }
                        strbuf_addstr(&non_note_path, entry.path);
                        add_non_note(t, strbuf_detach(&non_note_path, NULL),
-                                    entry.mode, entry.oid->hash);
+                                    entry.mode, entry.oid.hash);
                }
        }
        free(buf);
index 8c6b47cc777708d4f8e450337f2b9d205f43591b..e38af1a275a52a6cf5d7eda9789c4e061a735f74 100644 (file)
@@ -2100,7 +2100,7 @@ static int add_promisor_object(const struct object_id *oid,
                         */
                        return 0;
                while (tree_entry_gently(&desc, &entry))
-                       oidset_insert(set, entry.oid);
+                       oidset_insert(set, &entry.oid);
        } else if (obj->type == OBJ_COMMIT) {
                struct commit *commit = (struct commit *) obj;
                struct commit_list *parents = commit->parents;
index 13e0519c0241635c0c1fd14a7ff12e9478c70bd4..05fb390d55711fbf69047cbe7d22dee03da5d32c 100644 (file)
@@ -67,10 +67,10 @@ static void mark_tree_contents_uninteresting(struct repository *r,
        while (tree_entry(&desc, &entry)) {
                switch (object_type(entry.mode)) {
                case OBJ_TREE:
-                       mark_tree_uninteresting(r, lookup_tree(r, entry.oid));
+                       mark_tree_uninteresting(r, lookup_tree(r, &entry.oid));
                        break;
                case OBJ_BLOB:
-                       mark_blob_uninteresting(lookup_blob(r, entry.oid));
+                       mark_blob_uninteresting(lookup_blob(r, &entry.oid));
                        break;
                default:
                        /* Subproject commit - not in this repository */
index 0e5432461026eff15fe101cf017cd839702e5870..4ffa00ae0c21bd128404a80d4363c662d82d4dbb 100644 (file)
@@ -239,7 +239,7 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p,
                                                DIFF_STATUS_ADDED;
 
                        if (tpi_valid) {
-                               oid_i = tp[i].entry.oid;
+                               oid_i = &tp[i].entry.oid;
                                mode_i = tp[i].entry.mode;
                        }
                        else {
@@ -280,7 +280,7 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p,
                        /* same rule as in emitthis */
                        int tpi_valid = tp && !(tp[i].entry.mode & S_IFXMIN_NEQ);
 
-                       parents_oid[i] = tpi_valid ? tp[i].entry.oid : NULL;
+                       parents_oid[i] = tpi_valid ? &tp[i].entry.oid : NULL;
                }
 
                strbuf_add(base, path, pathlen);
@@ -491,7 +491,7 @@ static struct combine_diff_path *ll_diff_tree_paths(
                                                continue;
 
                                        /* diff(t,pi) != ΓΈ */
-                                       if (!oideq(t.entry.oid, tp[i].entry.oid) ||
+                                       if (!oideq(&t.entry.oid, &tp[i].entry.oid) ||
                                            (t.entry.mode != tp[i].entry.mode))
                                                continue;
 
index 1e040fc20e09f3ff93b78f9f0f90a81f9a154827..56b951d3cb028121994c29daa1bda41969d13a45 100644 (file)
@@ -48,7 +48,8 @@ static int decode_tree_entry(struct tree_desc *desc, const char *buf, unsigned l
        /* Initialize the descriptor entry */
        desc->entry.path = path;
        desc->entry.mode = canon_mode(mode);
-       desc->entry.oid  = (const struct object_id *)(path + len);
+       desc->entry.pathlen = len - 1;
+       hashcpy(desc->entry.oid.hash, (const unsigned char *)path + len);
 
        return 0;
 }
@@ -107,7 +108,7 @@ static void entry_extract(struct tree_desc *t, struct name_entry *a)
 static int update_tree_entry_internal(struct tree_desc *desc, struct strbuf *err)
 {
        const void *buf = desc->buffer;
-       const unsigned char *end = desc->entry.oid->hash + the_hash_algo->rawsz;
+       const unsigned char *end = (const unsigned char *)desc->entry.path + desc->entry.pathlen + 1 + the_hash_algo->rawsz;
        unsigned long size = desc->size;
        unsigned long len = end - (const unsigned char *)buf;
 
@@ -175,9 +176,11 @@ void setup_traverse_info(struct traverse_info *info, const char *base)
                pathlen--;
        info->pathlen = pathlen ? pathlen + 1 : 0;
        info->name.path = base;
-       info->name.oid = (void *)(base + pathlen + 1);
-       if (pathlen)
+       info->name.pathlen = pathlen;
+       if (pathlen) {
+               hashcpy(info->name.oid.hash, (const unsigned char *)base + pathlen + 1);
                info->prev = &dummy;
+       }
 }
 
 char *make_traverse_path(char *path, const struct traverse_info *info, const struct name_entry *n)
index 196831007e618f808661bf4b7f54030890f48563..08d349c54ffa413347bbf7237c84371bda0878e1 100644 (file)
@@ -1,11 +1,14 @@
 #ifndef TREE_WALK_H
 #define TREE_WALK_H
 
+#include "cache.h"
+
 struct strbuf;
 
 struct name_entry {
-       const struct object_id *oid;
+       struct object_id oid;
        const char *path;
+       int pathlen;
        unsigned int mode;
 };
 
@@ -19,12 +22,12 @@ static inline const struct object_id *tree_entry_extract(struct tree_desc *desc,
 {
        *pathp = desc->entry.path;
        *modep = desc->entry.mode;
-       return desc->entry.oid;
+       return &desc->entry.oid;
 }
 
 static inline int tree_entry_len(const struct name_entry *ne)
 {
-       return (const char *)ne->oid - ne->path - 1;
+       return ne->pathlen;
 }
 
 /*
diff --git a/tree.c b/tree.c
index 215d3fdc7c4af2ef2faca1cf5d5d0b5de52b84a8..7badea00094a98220b37874f60d1813abd42decb 100644 (file)
--- a/tree.c
+++ b/tree.c
@@ -84,7 +84,7 @@ static int read_tree_1(struct tree *tree, struct strbuf *base,
                                continue;
                }
 
-               switch (fn(entry.oid, base,
+               switch (fn(&entry.oid, base,
                           entry.path, entry.mode, stage, context)) {
                case 0:
                        continue;
@@ -95,19 +95,19 @@ static int read_tree_1(struct tree *tree, struct strbuf *base,
                }
 
                if (S_ISDIR(entry.mode))
-                       oidcpy(&oid, entry.oid);
+                       oidcpy(&oid, &entry.oid);
                else if (S_ISGITLINK(entry.mode)) {
                        struct commit *commit;
 
-                       commit = lookup_commit(the_repository, entry.oid);
+                       commit = lookup_commit(the_repository, &entry.oid);
                        if (!commit)
                                die("Commit %s in submodule path %s%s not found",
-                                   oid_to_hex(entry.oid),
+                                   oid_to_hex(&entry.oid),
                                    base->buf, entry.path);
 
                        if (parse_commit(commit))
                                die("Invalid commit %s in submodule path %s%s",
-                                   oid_to_hex(entry.oid),
+                                   oid_to_hex(&entry.oid),
                                    base->buf, entry.path);
 
                        oidcpy(&oid, get_commit_tree_oid(commit));
index 6d53cbfc865096ea41028c0601aa12d6eeb8a145..734828fda2821fa2c2306717a44ebf95659ca988 100644 (file)
@@ -679,7 +679,7 @@ static int switch_cache_bottom(struct traverse_info *info)
 
 static inline int are_same_oid(struct name_entry *name_j, struct name_entry *name_k)
 {
-       return name_j->oid && name_k->oid && oideq(name_j->oid, name_k->oid);
+       return !is_null_oid(&name_j->oid) && !is_null_oid(&name_k->oid) && oideq(&name_j->oid, &name_k->oid);
 }
 
 static int all_trees_same_as_cache_tree(int n, unsigned long dirmask,
@@ -857,7 +857,7 @@ static int traverse_trees_recursive(int n, unsigned long dirmask,
                else {
                        const struct object_id *oid = NULL;
                        if (dirmask & 1)
-                               oid = names[i].oid;
+                               oid = &names[i].oid;
                        buf[nr_buf++] = fill_tree_descriptor(t + i, oid);
                }
        }
@@ -981,7 +981,7 @@ static struct cache_entry *create_ce_entry(const struct traverse_info *info,
        ce->ce_mode = create_ce_mode(n->mode);
        ce->ce_flags = create_ce_flags(stage);
        ce->ce_namelen = len;
-       oidcpy(&ce->oid, n->oid);
+       oidcpy(&ce->oid, &n->oid);
        make_traverse_path(ce->name, info, n);
 
        return ce;
index 96990d84dabfdd34e169c8e9fcfd656633e4f31e..d74ae59c77fb3626be0af291c6ee6fbb9c52dbb1 100644 (file)
--- a/walker.c
+++ b/walker.c
@@ -50,13 +50,13 @@ static int process_tree(struct walker *walker, struct tree *tree)
                        continue;
                if (S_ISDIR(entry.mode)) {
                        struct tree *tree = lookup_tree(the_repository,
-                                                       entry.oid);
+                                                       &entry.oid);
                        if (tree)
                                obj = &tree->object;
                }
                else {
                        struct blob *blob = lookup_blob(the_repository,
-                                                       entry.oid);
+                                                       &entry.oid);
                        if (blob)
                                obj = &blob->object;
                }