Too deep delta chains can cause stack overflow in get_base_data(). Set a hard limit so that index-pack does not run out of stack. Also stop people from producing such a long delta chains using "pack-object --depth=<too large>" Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- I used to make very long delta chains and triggered this in index-pack. I did not care reporting because it's my fault anyway. Think again, index-pack is called at server side and a malicious client can trigger this. This patch does not improve the situation much, but at least we won't get sigsegv at server side. builtin/index-pack.c | 12 ++++++++++-- builtin/pack-objects.c | 3 +++ pack.h | 2 ++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 0945adb..cfb8cb2 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -504,13 +504,16 @@ static int is_delta_type(enum object_type type) return (type == OBJ_REF_DELTA || type == OBJ_OFS_DELTA); } -static void *get_base_data(struct base_data *c) +static void *get_base_data_1(struct base_data *c, int depth) { + if (depth > MAX_DELTA_DEPTH) + die("index-pack: too long delta chain"); + if (!c->data) { struct object_entry *obj = c->obj; if (is_delta_type(obj->type)) { - void *base = get_base_data(c->base); + void *base = get_base_data_1(c->base, depth + 1); void *raw = get_data_from_pack(obj); c->data = patch_delta( base, c->base->size, @@ -530,6 +533,11 @@ static void *get_base_data(struct base_data *c) return c->data; } +static void *get_base_data(struct base_data *c) +{ + return get_base_data_1(c, 0); +} + static void resolve_delta(struct object_entry *delta_obj, struct base_data *base, struct base_data *result) { diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 824ecee..85ee04b 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -2508,6 +2508,9 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) if (keep_unreachable && unpack_unreachable) die("--keep-unreachable and --unpack-unreachable are incompatible."); + if (depth > MAX_DELTA_DEPTH) + die("--depth exceeds %d", MAX_DELTA_DEPTH); + if (progress && all_progress_implied) progress = 2; diff --git a/pack.h b/pack.h index 722a54e..b8f60c3 100644 --- a/pack.h +++ b/pack.h @@ -3,6 +3,8 @@ #include "object.h" +#define MAX_DELTA_DEPTH 128 + /* * Packed object header */ -- 1.7.8.36.g69ee2 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html