diff options
author | Michael Haggerty <mhagger@alum.mit.edu> | 2014-03-13 10:19:08 +0100 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2014-03-13 10:57:48 -0700 |
commit | 2f29e0c6fa5d312c4e0675b0dd23d3126b9f55fa (patch) | |
tree | 9fdd08d73367ffe80b4d0f403ee8c42d65115d53 /entry.c | |
parent | f63272a35e03a9895c468d1a698dabaa4c3d9273 (diff) | |
download | git-2f29e0c6fa5d312c4e0675b0dd23d3126b9f55fa.tar.gz |
entry.c: fix possible buffer overflow in remove_subtree()mh/remove-subtree-long-pathname-fix
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>
Diffstat (limited to 'entry.c')
-rw-r--r-- | entry.c | 34 |
1 files changed, 17 insertions, 17 deletions
@@ -44,33 +44,33 @@ static void create_directories(const char *path, int path_len, free(buf); } -static void remove_subtree(const char *path) +static void remove_subtree(struct strbuf *path) { - DIR *dir = opendir(path); + DIR *dir = opendir(path->buf); struct dirent *de; - char pathbuf[PATH_MAX]; - char *name; + int origlen = path->len; if (!dir) - die_errno("cannot opendir '%s'", path); - strcpy(pathbuf, path); - name = pathbuf + strlen(path); - *name++ = '/'; + die_errno("cannot opendir '%s'", path->buf); while ((de = readdir(dir)) != NULL) { struct stat st; + if (is_dot_or_dotdot(de->d_name)) continue; - strcpy(name, de->d_name); - if (lstat(pathbuf, &st)) - die_errno("cannot lstat '%s'", pathbuf); + + strbuf_addch(path, '/'); + strbuf_addstr(path, de->d_name); + if (lstat(path->buf, &st)) + die_errno("cannot lstat '%s'", path->buf); if (S_ISDIR(st.st_mode)) - remove_subtree(pathbuf); - else if (unlink(pathbuf)) - die_errno("cannot unlink '%s'", pathbuf); + remove_subtree(path); + else if (unlink(path->buf)) + die_errno("cannot unlink '%s'", path->buf); + strbuf_setlen(path, origlen); } closedir(dir); - if (rmdir(path)) - die_errno("cannot rmdir '%s'", path); + if (rmdir(path->buf)) + die_errno("cannot rmdir '%s'", path->buf); } static int create_file(const char *path, unsigned int mode) @@ -271,7 +271,7 @@ int checkout_entry(struct cache_entry *ce, return 0; if (!state->force) return error("%s is a directory", path.buf); - remove_subtree(path.buf); + remove_subtree(&path); } else if (unlink(path.buf)) return error("unable to unlink old '%s' (%s)", path.buf, strerror(errno)); |