Skip to content

Commit 72695d8

Browse files
Byrongitster
authored andcommitted
mv: handle lstat() failure correctly
When moving a directory onto another with `git mv` various checks are performed. One of of these validates that the destination is not existing. When calling `lstat` on the destination path and it fails as the path doesn't exist, some environments seem to overwrite the passed in `stat` memory nonetheless (I observed this issue on debian 12 of x86_64, running on OrbStack on ARM, emulated with Rosetta). This would affect the code that followed as it would still acccess a now modified `st` structure, which now seems to contain uninitialized memory. `S_ISDIR(st_dir_mode)` would then typically return false causing the code to run into a bad case. The fix avoids overwriting the existing `st` structure, providing an alternative that exists only for that purpose. Note that this patch minimizes complexity instead of stack-frame size. Signed-off-by: Sebastian Thiel <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent fb7d80e commit 72695d8

File tree

2 files changed

+9
-2
lines changed

2 files changed

+9
-2
lines changed

builtin/mv.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
183183
int src_dir_nr = 0, src_dir_alloc = 0;
184184
struct strbuf a_src_dir = STRBUF_INIT;
185185
enum update_mode *modes, dst_mode = 0;
186-
struct stat st;
186+
struct stat st, dest_st;
187187
struct string_list src_for_dst = STRING_LIST_INIT_NODUP;
188188
struct lock_file lock_file = LOCK_INIT;
189189
struct cache_entry *ce;
@@ -303,7 +303,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
303303
goto act_on_entry;
304304
}
305305
if (S_ISDIR(st.st_mode)
306-
&& lstat(dst, &st) == 0) {
306+
&& lstat(dst, &dest_st) == 0) {
307307
bad = _("cannot move directory over file");
308308
goto act_on_entry;
309309
}

t/t7001-mv.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,13 @@ test_expect_success 'do not move directory over existing directory' '
174174
test_must_fail git mv path2 path0
175175
'
176176

177+
test_expect_success 'rename directory to non-existing directory' '
178+
mkdir dir-a &&
179+
>dir-a/f &&
180+
git add dir-a &&
181+
git mv dir-a non-existing-dir
182+
'
183+
177184
test_expect_success 'move into "."' '
178185
git mv path1/path2/ .
179186
'

0 commit comments

Comments
 (0)