Skip to content

Commit 436e7a7

Browse files
spearcegitster
authored andcommitted
Don't allow fast-import tree delta chains to exceed maximum depth
Brian Downing noticed fast-import can produce tree depths of up to 6,035 objects and even deeper. Long delta chains can create very small packfiles but cause problems during repacking as git needs to unpack each tree to count the reachable blobs. What's happening here is the active branch cache isn't big enough. We're swapping out the branch and thus recycling the tree information (struct tree_content) back into the free pool. When we later reload the tree we set the delta_depth to 0 but we kept the tree we just reloaded as a delta base. So if the tree we reloaded was already at the maximum depth we wouldn't know it and make the new tree a delta. Multiply the number of times the branch cache has to swap out the tree times max_depth (10) and you get the maximum delta depth of a tree created by fast-import. In Brian's case above the active branch cache had to swap the branch out 603/604 times during this import to produce a tree with a delta depth of 6035. Acked-by: Brian Downing <bdowning@lavos.net> Signed-off-by: Shawn O. Pearce <spearce@spearce.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 245de36 commit 436e7a7

File tree

1 file changed

+13
-7
lines changed

1 file changed

+13
-7
lines changed

fast-import.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,16 @@ Format of STDIN stream:
154154

155155
#define PACK_ID_BITS 16
156156
#define MAX_PACK_ID ((1<<PACK_ID_BITS)-1)
157+
#define DEPTH_BITS 13
158+
#define MAX_DEPTH ((1<<DEPTH_BITS)-1)
157159

158160
struct object_entry
159161
{
160162
struct object_entry *next;
161163
uint32_t offset;
162-
unsigned type : TYPE_BITS;
163-
unsigned pack_id : PACK_ID_BITS;
164+
uint32_t type : TYPE_BITS,
165+
pack_id : PACK_ID_BITS,
166+
depth : DEPTH_BITS;
164167
unsigned char sha1[20];
165168
};
166169

@@ -1105,7 +1108,7 @@ static int store_object(
11051108
unsigned pos = sizeof(hdr) - 1;
11061109

11071110
delta_count_by_type[type]++;
1108-
last->depth++;
1111+
e->depth = last->depth + 1;
11091112

11101113
hdrlen = encode_header(OBJ_OFS_DELTA, deltalen, hdr);
11111114
write_or_die(pack_data->pack_fd, hdr, hdrlen);
@@ -1117,8 +1120,7 @@ static int store_object(
11171120
write_or_die(pack_data->pack_fd, hdr + pos, sizeof(hdr) - pos);
11181121
pack_size += sizeof(hdr) - pos;
11191122
} else {
1120-
if (last)
1121-
last->depth = 0;
1123+
e->depth = 0;
11221124
hdrlen = encode_header(type, datlen, hdr);
11231125
write_or_die(pack_data->pack_fd, hdr, hdrlen);
11241126
pack_size += hdrlen;
@@ -1134,6 +1136,7 @@ static int store_object(
11341136
free(last->data);
11351137
last->data = dat;
11361138
last->offset = e->offset;
1139+
last->depth = e->depth;
11371140
last->len = datlen;
11381141
}
11391142
return 0;
@@ -1181,7 +1184,7 @@ static void load_tree(struct tree_entry *root)
11811184
if (myoe && myoe->pack_id != MAX_PACK_ID) {
11821185
if (myoe->type != OBJ_TREE)
11831186
die("Not a tree: %s", sha1_to_hex(sha1));
1184-
t->delta_depth = 0;
1187+
t->delta_depth = myoe->depth;
11851188
buf = gfi_unpack_entry(myoe, &size);
11861189
} else {
11871190
enum object_type type;
@@ -2347,8 +2350,11 @@ int main(int argc, const char **argv)
23472350
}
23482351
else if (!prefixcmp(a, "--max-pack-size="))
23492352
max_packsize = strtoumax(a + 16, NULL, 0) * 1024 * 1024;
2350-
else if (!prefixcmp(a, "--depth="))
2353+
else if (!prefixcmp(a, "--depth=")) {
23512354
max_depth = strtoul(a + 8, NULL, 0);
2355+
if (max_depth > MAX_DEPTH)
2356+
die("--depth cannot exceed %u", MAX_DEPTH);
2357+
}
23522358
else if (!prefixcmp(a, "--active-branches="))
23532359
max_active_branches = strtoul(a + 18, NULL, 0);
23542360
else if (!prefixcmp(a, "--import-marks="))

0 commit comments

Comments
 (0)