Skip to content

Commit be20128

Browse files
peffgitster
authored andcommitted
add core.maxTreeDepth config
Most of our tree traversal algorithms use recursion to visit sub-trees. For pathologically large trees, this can cause us to run out of stack space and abort in an uncontrolled way. Let's put our own limit here so that we can fail gracefully rather than segfaulting. In similar cases where we recursed along the commit graph, we rewrote the algorithms to avoid recursion and keep any stack data on the heap. But the commit graph is meant to grow without bound, whereas it's not an imposition to put a limit on the maximum size of tree we'll handle. And this has a bonus side effect: coupled with a limit on individual tree entry names, this limits the total size of a path we may encounter. This gives us an extra protection against code handling long path names which may suffer from integer overflows in the size (which could then be exploited by malicious trees). The default of 4096 is set to be much longer than anybody would care about in the real world. Even with single-letter interior tree names (like "a/b/c"), such a path is at least 8191 bytes. While most operating systems will let you create such a path incrementally, trying to reference the whole thing in a system call (as Git would do when actually trying to access it) will result in ENAMETOOLONG. Coupled with the recent fsck.largePathname warning, the maximum total pathname Git will handle is (by default) 16MB. This config option doesn't do anything yet; future patches will convert various algorithms to respect the limit. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0fbcaef commit be20128

File tree

4 files changed

+13
-0
lines changed

4 files changed

+13
-0
lines changed

Documentation/config/core.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,3 +736,9 @@ core.abbrev::
736736
If set to "no", no abbreviation is made and the object names
737737
are shown in their full length.
738738
The minimum length is 4.
739+
740+
core.maxTreeDepth::
741+
The maximum depth Git is willing to recurse while traversing a
742+
tree (e.g., "a/b/cde/f" has a depth of 4). This is a fail-safe
743+
to allow Git to abort cleanly, and should not generally need to
744+
be adjusted. The default is 4096.

config.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1801,6 +1801,11 @@ static int git_default_core_config(const char *var, const char *value,
18011801
return 0;
18021802
}
18031803

1804+
if (!strcmp(var, "core.maxtreedepth")) {
1805+
max_allowed_tree_depth = git_config_int(var, value, ctx->kvi);
1806+
return 0;
1807+
}
1808+
18041809
/* Add other config variables here and to Documentation/config.txt. */
18051810
return platform_core_config(var, value, ctx, cb);
18061811
}

environment.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ int merge_log_config = -1;
8181
int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
8282
unsigned long pack_size_limit_cfg;
8383
enum log_refs_config log_all_ref_updates = LOG_REFS_UNSET;
84+
int max_allowed_tree_depth = 4096;
8485

8586
#ifndef PROTECT_HFS_DEFAULT
8687
#define PROTECT_HFS_DEFAULT 0

environment.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ extern size_t packed_git_limit;
132132
extern size_t delta_base_cache_limit;
133133
extern unsigned long big_file_threshold;
134134
extern unsigned long pack_size_limit_cfg;
135+
extern int max_allowed_tree_depth;
135136

136137
/*
137138
* Accessors for the core.sharedrepository config which lazy-load the value

0 commit comments

Comments
 (0)