From: Junio C Hamano Date: Thu, 15 Feb 2018 22:55:41 +0000 (-0800) Subject: Merge branch 'jt/fsck-code-cleanup' X-Git-Tag: v2.17.0-rc0~99 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/52b7ab31d08d3e29870f7085c64de936e109f05d?hp=-c Merge branch 'jt/fsck-code-cleanup' Plug recently introduced leaks in fsck. * jt/fsck-code-cleanup: fsck: fix leak when traversing trees --- 52b7ab31d08d3e29870f7085c64de936e109f05d diff --combined builtin/fsck.c index 7a8a679d4f,5aa4a1b336..9981db2263 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@@ -15,7 -15,6 +15,7 @@@ #include "progress.h" #include "streaming.h" #include "decorate.h" +#include "packfile.h" #define REACHABLE 0x0001 #define SEEN 0x0002 @@@ -149,15 -148,6 +149,15 @@@ static int mark_object(struct object *o if (obj->flags & REACHABLE) return 0; obj->flags |= REACHABLE; + + if (is_promisor_object(&obj->oid)) + /* + * Further recursion does not need to be performed on this + * object since it is a promisor object (so it does not need to + * be added to "pending"). + */ + return 0; + if (!(obj->flags & HAS_OBJ)) { if (parent && !has_object_file(&obj->oid)) { printf("broken link from %7s %s\n", @@@ -180,7 -170,13 +180,13 @@@ static void mark_object_reachable(struc static int traverse_one_object(struct object *obj) { - return fsck_walk(obj, obj, &fsck_walk_options); + int result = fsck_walk(obj, obj, &fsck_walk_options); + + if (obj->type == OBJ_TREE) { + struct tree *tree = (struct tree *)obj; + free_tree_buffer(tree); + } + return result; } static int traverse_reachable(void) @@@ -189,9 -185,14 +195,9 @@@ unsigned int nr = 0; int result = 0; if (show_progress) - progress = start_progress_delay(_("Checking connectivity"), 0, 0, 2); + progress = start_delayed_progress(_("Checking connectivity"), 0); while (pending.nr) { - struct object_array_entry *entry; - struct object *obj; - - entry = pending.objects + --pending.nr; - obj = entry->item; - result |= traverse_one_object(obj); + result |= traverse_one_object(object_array_pop(&pending)); display_progress(progress, ++nr); } stop_progress(&progress); @@@ -217,8 -218,6 +223,8 @@@ static void check_reachable_object(stru * do a full fsck */ if (!(obj->flags & HAS_OBJ)) { + if (is_promisor_object(&obj->oid)) + return; if (has_sha1_pack(obj->oid.hash)) return; /* it is in pack - forget about it */ printf("missing %s %s\n", printable_type(obj), @@@ -333,8 -332,6 +339,8 @@@ static void check_connectivity(void static int fsck_obj(struct object *obj) { + int err; + if (obj->flags & SEEN) return 0; obj->flags |= SEEN; @@@ -345,13 -342,20 +351,13 @@@ if (fsck_walk(obj, NULL, &fsck_obj_options)) objerror(obj, "broken links"); - if (fsck_object(obj, NULL, 0, &fsck_obj_options)) - return -1; - - if (obj->type == OBJ_TREE) { - struct tree *item = (struct tree *) obj; - - free_tree_buffer(item); - } + err = fsck_object(obj, NULL, 0, &fsck_obj_options); + if (err) + goto out; if (obj->type == OBJ_COMMIT) { struct commit *commit = (struct commit *) obj; - free_commit_buffer(commit); - if (!commit->parents && show_root) printf("root %s\n", describe_object(&commit->object)); } @@@ -367,12 -371,7 +373,12 @@@ } } - return 0; +out: + if (obj->type == OBJ_TREE) + free_tree_buffer((struct tree *)obj); + if (obj->type == OBJ_COMMIT) + free_commit_buffer((struct commit *)obj); + return err; } static int fsck_obj_buffer(const struct object_id *oid, enum object_type type, @@@ -409,7 -408,7 +415,7 @@@ static void fsck_handle_reflog_oid(cons xstrfmt("%s@{%"PRItime"}", refname, timestamp)); obj->flags |= USED; mark_object_reachable(obj); - } else { + } else if (!is_promisor_object(oid)) { error("%s: invalid reflog entry %s", refname, oid_to_hex(oid)); errors_found |= ERROR_REACHABLE; } @@@ -445,14 -444,6 +451,14 @@@ static int fsck_handle_ref(const char * obj = parse_object(oid); if (!obj) { + if (is_promisor_object(oid)) { + /* + * Increment default_refs anyway, because this is a + * valid ref. + */ + default_refs++; + return 0; + } error("%s: invalid sha1 pointer %s", refname, oid_to_hex(oid)); errors_found |= ERROR_REACHABLE; /* We'll continue with the rest despite the error.. */ @@@ -574,7 -565,7 +580,7 @@@ static int fsck_head_link(void if (verbose) fprintf(stderr, "Checking HEAD link\n"); - head_points_at = resolve_ref_unsafe("HEAD", 0, head_oid.hash, NULL); + head_points_at = resolve_ref_unsafe("HEAD", 0, &head_oid, NULL); if (!head_points_at) { errors_found |= ERROR_REFS; return error("Invalid HEAD"); @@@ -678,9 -669,6 +684,9 @@@ int cmd_fsck(int argc, const char **arg int i; struct alternate_object_database *alt; + /* fsck knows how to handle missing promisor objects */ + fetch_if_missing = 0; + errors_found = 0; check_replace_refs = 0; @@@ -748,14 -736,12 +754,14 @@@ for (i = 0; i < argc; i++) { const char *arg = argv[i]; - unsigned char sha1[20]; - if (!get_sha1(arg, sha1)) { - struct object *obj = lookup_object(sha1); + struct object_id oid; + if (!get_oid(arg, &oid)) { + struct object *obj = lookup_object(oid.hash); if (!obj || !(obj->flags & HAS_OBJ)) { - error("%s: object missing", sha1_to_hex(sha1)); + if (is_promisor_object(&oid)) + continue; + error("%s: object missing", oid_to_hex(&oid)); errors_found |= ERROR_OBJECT; continue; } @@@ -783,7 -769,6 +789,7 @@@ if (keep_cache_objects) { verify_index_checksum = 1; + verify_ce_order = 1; read_cache(); for (i = 0; i < active_nr; i++) { unsigned int mode;