entry.c: fix possible buffer overflow in remove_subtree()
remove_subtree() manipulated path in a fixed-size buffer even though the length of the input, let alone the length of entries within the directory, were not known in advance. Change the function to take a strbuf argument and use that object as its scratch space. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Michael Haggerty committed
Mar 13, 2014 at 10:19 UTC
2f29e0c6fa5d312c4e0675b0dd23d3126b9f55fa
1 file changed
+17
-17
entry.c
+17
-17
@@ -44,33 +44,33 @@ static void create_directories(const char *path, int path_len,
44
free(buf);
45
}
46
47
-static void remove_subtree(const char *path)
47
+static void remove_subtree(struct strbuf *path)
48
{
49
- DIR *dir = opendir(path);
49
+ DIR *dir = opendir(path->buf);
50
struct dirent *de;
51
- char pathbuf[PATH_MAX];
52
- char *name;
51
+ int origlen = path->len;
52
53
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);
55
while ((de = readdir(dir)) != NULL) {
56
struct stat st;
57
+
58
if (is_dot_or_dotdot(de->d_name))
59
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);
65
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);
70
}
71
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);
74
}
75
76
static int create_file(const char *path, unsigned int mode)
@@ -271,7 +271,7 @@ int checkout_entry(struct cache_entry *ce,
271
return 0;
272
if (!state->force)
273
return error("%s is a directory", path.buf);
274
- remove_subtree(path.buf);
274
+ remove_subtree(&path);
275
} else if (unlink(path.buf))
276
return error("unable to unlink old '%s' (%s)",
277
path.buf, strerror(errno));