Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/tree.c
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2023-08-31 09:21:55 +0300
committerJunio C Hamano <gitster@pobox.com>2023-09-01 01:51:08 +0300
commit1ee7a5c388626d049af61c9909eefe7640a26fc9 (patch)
treea8150322b67b8a9a384386527b5dbc2f0eb0f2e1 /tree.c
parentf1f63a481bcaaa2124b5f0395abec6b457888bf1 (diff)
read_tree(): respect max_allowed_tree_depth
The read_tree() function reads trees recursively (via its read_tree_at() helper). This can cause it to run out of stack space on very deep trees. Let's teach it about the new core.maxTreeDepth option. The easiest way to demonstrate this is via "ls-tree -r", which the test covers. Note that I needed a tree depth of ~30k to trigger a segfault on my Linux system, not the 4100 used by our "big" test in t6700. However, that test still tells us what we want: that the default 4096 limit is enough to prevent segfaults on all platforms. We could bump it, but that increases the cost of the test setup for little gain. As an interesting side-note: when I originally wrote this patch about 4 years ago, I needed a depth of ~50k to segfault. But porting it forward, the number is much lower. Seemingly little things like cf0983213c (hash: add an algo member to struct object_id, 2021-04-26) take it from 32,722 to 29,080. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'tree.c')
-rw-r--r--tree.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/tree.c b/tree.c
index c745462f96..990f9c9854 100644
--- a/tree.c
+++ b/tree.c
@@ -10,11 +10,13 @@
#include "alloc.h"
#include "tree-walk.h"
#include "repository.h"
+#include "environment.h"
const char *tree_type = "tree";
int read_tree_at(struct repository *r,
struct tree *tree, struct strbuf *base,
+ int depth,
const struct pathspec *pathspec,
read_tree_fn_t fn, void *context)
{
@@ -24,6 +26,9 @@ int read_tree_at(struct repository *r,
int len, oldlen = base->len;
enum interesting retval = entry_not_interesting;
+ if (depth > max_allowed_tree_depth)
+ return error("exceeded maximum allowed tree depth");
+
if (parse_tree(tree))
return -1;
@@ -74,7 +79,7 @@ int read_tree_at(struct repository *r,
strbuf_add(base, entry.path, len);
strbuf_addch(base, '/');
retval = read_tree_at(r, lookup_tree(r, &oid),
- base, pathspec,
+ base, depth + 1, pathspec,
fn, context);
strbuf_setlen(base, oldlen);
if (retval)
@@ -89,7 +94,7 @@ int read_tree(struct repository *r,
read_tree_fn_t fn, void *context)
{
struct strbuf sb = STRBUF_INIT;
- int ret = read_tree_at(r, tree, &sb, pathspec, fn, context);
+ int ret = read_tree_at(r, tree, &sb, 0, pathspec, fn, context);
strbuf_release(&sb);
return ret;
}