From 38d2ab633180e183653d781e5787e2842000f09f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Tue, 29 Jul 2014 20:50:26 +0700 Subject: [PATCH] prune --repos: fix uninitialized access MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit There's a code path in prune_repo_dir() that does not initialize 'st' buffer, which is checked by the caller, prune_repos_dir(). Instead of leaking some prune logic out to prune_repos_dir(), move 'st' into prune_repo_dir(). Another bug that is fixed while at there is the "return 0" at the end of prune_repo_dir() instead of '1', meaning "keep the checkout" while we want "keep the checkout _unless_ its last update is older than expire limit". Set correct expire limit in the test as well. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- builtin/prune.c | 16 ++++++---------- t/t2026-prune-linked-checkouts.sh | 2 +- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/builtin/prune.c b/builtin/prune.c index 28b7adf911..e72c3917ef 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -112,8 +112,9 @@ static void prune_object_dir(const char *path) } } -static int prune_repo_dir(const char *id, struct stat *st, struct strbuf *reason) +static int prune_repo_dir(const char *id, struct strbuf *reason) { + struct stat st; char *path; int fd, len; @@ -123,26 +124,23 @@ static int prune_repo_dir(const char *id, struct stat *st, struct strbuf *reason } if (file_exists(git_path("repos/%s/locked", id))) return 0; - if (stat(git_path("repos/%s/gitdir", id), st)) { - st->st_mtime = expire; + if (stat(git_path("repos/%s/gitdir", id), &st)) { strbuf_addf(reason, _("Removing repos/%s: gitdir file does not exist"), id); return 1; } fd = open(git_path("repos/%s/gitdir", id), O_RDONLY); if (fd < 0) { - st->st_mtime = expire; strbuf_addf(reason, _("Removing repos/%s: unable to read gitdir file (%s)"), id, strerror(errno)); return 1; } - len = st->st_size; + len = st.st_size; path = xmalloc(len + 1); read_in_full(fd, path, len); close(fd); while (len && (path[len - 1] == '\n' || path[len - 1] == '\r')) len--; if (!len) { - st->st_mtime = expire; strbuf_addf(reason, _("Removing repos/%s: invalid gitdir file"), id); free(path); return 1; @@ -162,7 +160,7 @@ static int prune_repo_dir(const char *id, struct stat *st, struct strbuf *reason return 1; } free(path); - return 0; + return st.st_mtime <= expire; } static void prune_repos_dir(void) @@ -172,15 +170,13 @@ static void prune_repos_dir(void) DIR *dir = opendir(git_path("repos")); struct dirent *d; int ret; - struct stat st; if (!dir) return; while ((d = readdir(dir)) != NULL) { if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) continue; strbuf_reset(&reason); - if (!prune_repo_dir(d->d_name, &st, &reason) || - st.st_mtime > expire) + if (!prune_repo_dir(d->d_name, &reason)) continue; if (show_only || verbose) printf("%s\n", reason.buf); diff --git a/t/t2026-prune-linked-checkouts.sh b/t/t2026-prune-linked-checkouts.sh index 4ccfa4ee8a..79d84cba42 100755 --- a/t/t2026-prune-linked-checkouts.sh +++ b/t/t2026-prune-linked-checkouts.sh @@ -77,7 +77,7 @@ test_expect_success 'not prune recent checkouts' ' mkdir zz && mkdir -p .git/repos/jlm && echo "$TRASH_DIRECTORY"/zz >.git/repos/jlm/gitdir && - git prune --repos --verbose && + git prune --repos --verbose --expire=2.days.ago && test -d .git/repos/jlm ' -- 2.11.4.GIT