Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Commit a3236f4

Browse files
committed
Merge branch 'mh/remove-subtree-long-pathname-fix' into maint
* mh/remove-subtree-long-pathname-fix: entry.c: fix possible buffer overflow in remove_subtree() checkout_entry(): use the strbuf throughout the function
2 parents e99a69d + 2f29e0c commit a3236f4

File tree

1 file changed

+32
-32
lines changed

1 file changed

+32
-32
lines changed

entry.c

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -44,33 +44,33 @@ static void create_directories(const char *path, int path_len,
4444
free(buf);
4545
}
4646

47-
static void remove_subtree(const char *path)
47+
static void remove_subtree(struct strbuf *path)
4848
{
49-
DIR *dir = opendir(path);
49+
DIR *dir = opendir(path->buf);
5050
struct dirent *de;
51-
char pathbuf[PATH_MAX];
52-
char *name;
51+
int origlen = path->len;
5352

5453
if (!dir)
55-
die_errno("cannot opendir '%s'", path);
56-
strcpy(pathbuf, path);
57-
name = pathbuf + strlen(path);
58-
*name++ = '/';
54+
die_errno("cannot opendir '%s'", path->buf);
5955
while ((de = readdir(dir)) != NULL) {
6056
struct stat st;
57+
6158
if (is_dot_or_dotdot(de->d_name))
6259
continue;
63-
strcpy(name, de->d_name);
64-
if (lstat(pathbuf, &st))
65-
die_errno("cannot lstat '%s'", pathbuf);
60+
61+
strbuf_addch(path, '/');
62+
strbuf_addstr(path, de->d_name);
63+
if (lstat(path->buf, &st))
64+
die_errno("cannot lstat '%s'", path->buf);
6665
if (S_ISDIR(st.st_mode))
67-
remove_subtree(pathbuf);
68-
else if (unlink(pathbuf))
69-
die_errno("cannot unlink '%s'", pathbuf);
66+
remove_subtree(path);
67+
else if (unlink(path->buf))
68+
die_errno("cannot unlink '%s'", path->buf);
69+
strbuf_setlen(path, origlen);
7070
}
7171
closedir(dir);
72-
if (rmdir(path))
73-
die_errno("cannot rmdir '%s'", path);
72+
if (rmdir(path->buf))
73+
die_errno("cannot rmdir '%s'", path->buf);
7474
}
7575

7676
static int create_file(const char *path, unsigned int mode)
@@ -245,27 +245,25 @@ static int check_path(const char *path, int len, struct stat *st, int skiplen)
245245
int checkout_entry(struct cache_entry *ce,
246246
const struct checkout *state, char *topath)
247247
{
248-
static struct strbuf path_buf = STRBUF_INIT;
249-
char *path;
248+
static struct strbuf path = STRBUF_INIT;
250249
struct stat st;
251-
int len;
252250

253251
if (topath)
254252
return write_entry(ce, topath, state, 1);
255253

256-
strbuf_reset(&path_buf);
257-
strbuf_add(&path_buf, state->base_dir, state->base_dir_len);
258-
strbuf_add(&path_buf, ce->name, ce_namelen(ce));
259-
path = path_buf.buf;
260-
len = path_buf.len;
254+
strbuf_reset(&path);
255+
strbuf_add(&path, state->base_dir, state->base_dir_len);
256+
strbuf_add(&path, ce->name, ce_namelen(ce));
261257

262-
if (!check_path(path, len, &st, state->base_dir_len)) {
258+
if (!check_path(path.buf, path.len, &st, state->base_dir_len)) {
263259
unsigned changed = ce_match_stat(ce, &st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE);
264260
if (!changed)
265261
return 0;
266262
if (!state->force) {
267263
if (!state->quiet)
268-
fprintf(stderr, "%s already exists, no checkout\n", path);
264+
fprintf(stderr,
265+
"%s already exists, no checkout\n",
266+
path.buf);
269267
return -1;
270268
}
271269

@@ -280,12 +278,14 @@ int checkout_entry(struct cache_entry *ce,
280278
if (S_ISGITLINK(ce->ce_mode))
281279
return 0;
282280
if (!state->force)
283-
return error("%s is a directory", path);
284-
remove_subtree(path);
285-
} else if (unlink(path))
286-
return error("unable to unlink old '%s' (%s)", path, strerror(errno));
281+
return error("%s is a directory", path.buf);
282+
remove_subtree(&path);
283+
} else if (unlink(path.buf))
284+
return error("unable to unlink old '%s' (%s)",
285+
path.buf, strerror(errno));
287286
} else if (state->not_new)
288287
return 0;
289-
create_directories(path, len, state);
290-
return write_entry(ce, path, state, 0);
288+
289+
create_directories(path.buf, path.len, state);
290+
return write_entry(ce, path.buf, state, 0);
291291
}

0 commit comments

Comments
 (0)