Skip to content

Commit 5235e56

Browse files
committed
Merge branch 'jk/leakfixes'
Memory leaks in "git mv" has been plugged. * jk/leakfixes: mv: replace src_dir with a strvec mv: factor out empty src_dir removal mv: move src_dir cleanup to end of cmd_mv() t-strvec: mark variable-arg helper with LAST_ARG_MUST_BE_NULL t-strvec: use va_end() to match va_start()
2 parents 718b50e + 64f8502 commit 5235e56

File tree

2 files changed

+29
-24
lines changed

2 files changed

+29
-24
lines changed

builtin/mv.c

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,28 @@ static int empty_dir_has_sparse_contents(const char *name)
156156
return ret;
157157
}
158158

159+
static void remove_empty_src_dirs(const char **src_dir, size_t src_dir_nr)
160+
{
161+
size_t i;
162+
struct strbuf a_src_dir = STRBUF_INIT;
163+
164+
for (i = 0; i < src_dir_nr; i++) {
165+
int dummy;
166+
strbuf_addstr(&a_src_dir, src_dir[i]);
167+
/*
168+
* if entries under a_src_dir are all moved away,
169+
* recursively remove a_src_dir to cleanup
170+
*/
171+
if (index_range_of_same_dir(a_src_dir.buf, a_src_dir.len,
172+
&dummy, &dummy) < 1) {
173+
remove_dir_recursively(&a_src_dir, 0);
174+
}
175+
strbuf_reset(&a_src_dir);
176+
}
177+
178+
strbuf_release(&a_src_dir);
179+
}
180+
159181
int cmd_mv(int argc, const char **argv, const char *prefix)
160182
{
161183
int i, flags, gitmodules_modified = 0;
@@ -175,9 +197,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
175197
struct strvec submodule_gitfiles_to_free = STRVEC_INIT;
176198
const char **submodule_gitfiles;
177199
char *dst_w_slash = NULL;
178-
const char **src_dir = NULL;
179-
int src_dir_nr = 0, src_dir_alloc = 0;
180-
struct strbuf a_src_dir = STRBUF_INIT;
200+
struct strvec src_dir = STRVEC_INIT;
181201
enum update_mode *modes, dst_mode = 0;
182202
struct stat st, dest_st;
183203
struct string_list src_for_dst = STRING_LIST_INIT_DUP;
@@ -323,8 +343,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
323343
/* last - first >= 1 */
324344
modes[i] |= WORKING_DIRECTORY;
325345

326-
ALLOC_GROW(src_dir, src_dir_nr + 1, src_dir_alloc);
327-
src_dir[src_dir_nr++] = src;
346+
strvec_push(&src_dir, src);
328347

329348
n = argc + last - first;
330349
REALLOC_ARRAY(modes, n);
@@ -538,25 +557,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
538557
}
539558
}
540559

541-
/*
542-
* cleanup the empty src_dirs
543-
*/
544-
for (i = 0; i < src_dir_nr; i++) {
545-
int dummy;
546-
strbuf_addstr(&a_src_dir, src_dir[i]);
547-
/*
548-
* if entries under a_src_dir are all moved away,
549-
* recursively remove a_src_dir to cleanup
550-
*/
551-
if (index_range_of_same_dir(a_src_dir.buf, a_src_dir.len,
552-
&dummy, &dummy) < 1) {
553-
remove_dir_recursively(&a_src_dir, 0);
554-
}
555-
strbuf_reset(&a_src_dir);
556-
}
557-
558-
strbuf_release(&a_src_dir);
559-
free(src_dir);
560+
remove_empty_src_dirs(src_dir.v, src_dir.nr);
560561

561562
if (dirty_paths.nr)
562563
advise_on_moving_dirty_path(&dirty_paths);
@@ -571,6 +572,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
571572
ret = 0;
572573

573574
out:
575+
strvec_clear(&src_dir);
574576
free(dst_w_slash);
575577
string_list_clear(&src_for_dst, 0);
576578
string_list_clear(&dirty_paths, 0);

t/unit-tests/t-strvec.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#define check_strvec(vec, ...) \
66
check_strvec_loc(TEST_LOCATION(), vec, __VA_ARGS__)
7+
LAST_ARG_MUST_BE_NULL
78
static void check_strvec_loc(const char *loc, struct strvec *vec, ...)
89
{
910
va_list ap;
@@ -22,11 +23,13 @@ static void check_strvec_loc(const char *loc, struct strvec *vec, ...)
2223
strbuf_addf(&msg, "strvec index %"PRIuMAX, (uintmax_t) nr);
2324
test_assert(loc, msg.buf, 0);
2425
strbuf_release(&msg);
26+
va_end(ap);
2527
return;
2628
}
2729

2830
nr++;
2931
}
32+
va_end(ap);
3033

3134
check_uint(vec->nr, ==, nr);
3235
check_uint(vec->alloc, >=, nr);

0 commit comments

Comments
 (0)