Skip to content

Commit c235d96

Browse files
committed
prune-packed: use strbuf to avoid having to worry about PATH_MAX
A/very/long/path/to/.git that becomes exactly PATH_MAX bytes long after suffixed with /objects/??/??38-hex??, would have overflown the on-stack pathname[] buffer. Noticed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent d7aced9 commit c235d96

File tree

1 file changed

+21
-17
lines changed

1 file changed

+21
-17
lines changed

builtin/prune-packed.c

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,58 +10,62 @@ static const char * const prune_packed_usage[] = {
1010

1111
static struct progress *progress;
1212

13-
static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts)
13+
static void prune_dir(int i, DIR *dir, struct strbuf *pathname, int opts)
1414
{
1515
struct dirent *de;
1616
char hex[40];
17+
int top_len = pathname->len;
1718

1819
sprintf(hex, "%02x", i);
1920
while ((de = readdir(dir)) != NULL) {
2021
unsigned char sha1[20];
2122
if (strlen(de->d_name) != 38)
2223
continue;
23-
memcpy(hex+2, de->d_name, 38);
24+
memcpy(hex + 2, de->d_name, 38);
2425
if (get_sha1_hex(hex, sha1))
2526
continue;
2627
if (!has_sha1_pack(sha1))
2728
continue;
28-
memcpy(pathname + len, de->d_name, 38);
29+
30+
strbuf_add(pathname, de->d_name, 38);
2931
if (opts & PRUNE_PACKED_DRY_RUN)
30-
printf("rm -f %s\n", pathname);
32+
printf("rm -f %s\n", pathname->buf);
3133
else
32-
unlink_or_warn(pathname);
34+
unlink_or_warn(pathname->buf);
3335
display_progress(progress, i + 1);
36+
strbuf_setlen(pathname, top_len);
3437
}
3538
}
3639

3740
void prune_packed_objects(int opts)
3841
{
3942
int i;
40-
static char pathname[PATH_MAX];
4143
const char *dir = get_object_directory();
42-
int len = strlen(dir);
44+
struct strbuf pathname = STRBUF_INIT;
45+
int top_len;
4346

47+
strbuf_addstr(&pathname, dir);
4448
if (opts & PRUNE_PACKED_VERBOSE)
4549
progress = start_progress_delay("Removing duplicate objects",
4650
256, 95, 2);
4751

48-
if (len > PATH_MAX - 42)
49-
die("impossible object directory");
50-
memcpy(pathname, dir, len);
51-
if (len && pathname[len-1] != '/')
52-
pathname[len++] = '/';
52+
if (pathname.len && pathname.buf[pathname.len - 1] != '/')
53+
strbuf_addch(&pathname, '/');
54+
55+
top_len = pathname.len;
5356
for (i = 0; i < 256; i++) {
5457
DIR *d;
5558

5659
display_progress(progress, i + 1);
57-
sprintf(pathname + len, "%02x/", i);
58-
d = opendir(pathname);
60+
strbuf_setlen(&pathname, top_len);
61+
strbuf_addf(&pathname, "%02x/", i);
62+
d = opendir(pathname.buf);
5963
if (!d)
6064
continue;
61-
prune_dir(i, d, pathname, len + 3, opts);
65+
prune_dir(i, d, &pathname, opts);
6266
closedir(d);
63-
pathname[len + 2] = '\0';
64-
rmdir(pathname);
67+
strbuf_setlen(&pathname, top_len + 2);
68+
rmdir(pathname.buf);
6569
}
6670
stop_progress(&progress);
6771
}

0 commit comments

Comments
 (0)