Re: [PATCH] Avoid infinite loop in malformed packfiles

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Jeff King <peff@xxxxxxxx> writes:

> I think it may be worth making this a configurable value
> (core.maxDeltaDepth or something). Nobody would generally need to tweak
> it, but it would give an escape hatch for getting people out of a broken
> situation ("git -c core.maxDeltaDepth=50000 repack" or similar).

... meaning "the pack I have has overlong delta chains to read, and
I am running repack to cut these chains down to more manageable
level"?  Makes sense.

As it may be a bit tricky to figure out where we should read such a
configuration for those who are new to our codebase, here is an
illustration to give a starting point.  Docs and tests are probably
needed, too.

 cache.h       | 1 +
 config.c      | 5 +++++
 environment.c | 1 +
 packfile.c    | 6 ++++++
 4 files changed, 13 insertions(+)

diff --git a/cache.h b/cache.h
index 0290849c19..b59d43f0ec 100644
--- a/cache.h
+++ b/cache.h
@@ -919,6 +919,7 @@ extern int minimum_abbrev, default_abbrev;
 extern int ignore_case;
 extern int assume_unchanged;
 extern int prefer_symlink_refs;
+extern int max_allowed_delta_depth;
 extern int warn_ambiguous_refs;
 extern int warn_on_object_refname_ambiguity;
 extern const char *apply_default_whitespace;
diff --git a/config.c b/config.c
index 2b79fe76ad..5f9114f847 100644
--- a/config.c
+++ b/config.c
@@ -1197,6 +1197,11 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
 		return 0;
 	}
 
+	if (!strcmp(var, "core.maxalloweddeltadepth")) {
+		max_allowed_delta_depth = git_config_int(var, value);
+		return 0;
+	}
+
 	if (!strcmp(var, "core.logallrefupdates")) {
 		if (value && !strcasecmp(value, "always"))
 			log_all_ref_updates = LOG_REFS_ALWAYS;
diff --git a/environment.c b/environment.c
index 52e0c979ba..d3f9a10799 100644
--- a/environment.c
+++ b/environment.c
@@ -27,6 +27,7 @@ int minimum_abbrev = 4, default_abbrev = -1;
 int ignore_case;
 int assume_unchanged;
 int prefer_symlink_refs;
+int max_allowed_delta_depth = 10000;
 int is_bare_repository_cfg = -1; /* unspecified */
 int warn_ambiguous_refs = 1;
 int warn_on_object_refname_ambiguity = 1;
diff --git a/packfile.c b/packfile.c
index 6ab5233613..2ea24a19dd 100644
--- a/packfile.c
+++ b/packfile.c
@@ -1715,6 +1715,12 @@ void *unpack_entry(struct repository *r, struct packed_git *p, off_t obj_offset,
 			break;
 		}
 
+		if (max_allowed_delta_depth < delta_stack_nr) {
+			error("overlong delta chain at offset %"PRIuMAX" from %s",
+			      (uintmax_t)curpos, p->pack_name);
+			goto out;
+		}
+
 		/* push object, proceed to base */
 		if (delta_stack_nr >= delta_stack_alloc
 		    && delta_stack == small_delta_stack) {








[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux