diff mbox series

[v3] builtin/mv.c: fix possible segfault in add_slash()

Message ID 20220909222736.279362-1-shaoxuan.yuan02@gmail.com (mailing list archive)
State Accepted
Commit 7ead46810b507828c1481eaea6d64b9ed635b8b7
Headers show
Series [v3] builtin/mv.c: fix possible segfault in add_slash() | expand

Commit Message

Shaoxuan Yuan Sept. 9, 2022, 10:27 p.m. UTC
A possible segfault was introduced in c08830de41 (mv: check if
<destination> is a SKIP_WORKTREE_DIR, 2022-08-09).

When running t7001 with SANITIZE=address, problem appears when running:

	git mv path1/path2/ .
or
	git mv directory ../
or
	any <destination> that makes dest_path[0] an empty string.

The add_slash() call could segfault when path argument to it is an empty
string, because it makes an out-of-bounds read to decide if an extra
slash '/' needs to be appended to it.

As add_slash() is used to make sure that a valid pathname to a file in
the given directory can be made by appending a filename after the value
returned from it, if path is an empty string, we want to return it
as-is.  The path to a file "F" in the top-level of the working tree
(i.e. path=="") is formed by appending "F" after "" (i.e. path) without
any slash in between.

So, just like the case where a non-empty path already ends with a slash,
return an empty path as-is.

Reported-by: Jeff King <peff@peff.net>
Helped-by: Jeff King <peff@peff.net>
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Derrick Stolee <derrickstolee@github.com>
Signed-off-by: Shaoxuan Yuan <shaoxuan.yuan02@gmail.com>
---
Range-diff against v2:
1:  1120dc7e6b ! 1:  569e618013 builtin/mv.c: fix possible segfault in add_slash()
    @@ Commit message
         or
                 any <destination> that makes dest_path[0] an empty string.
     
    -    The add_slash() call could segfault when dest_path[0] is an empty string,
    -    because it was accessing a null value in such case.
    -
    -    Change add_slash() to check the path argument is a non-empty string
    -    before accessing its value. If the path is empty, return it as-is.
    -
    -    Explanation:
    -
    -    It's OK for add_slash() to return an empty string as-is. add_slash()
    -    converts its path argument to the prefix (for "folder1/file1",
    -    "folder1/" is the prefix we mean here) for the result path. The path
    -    argument is an empty string _iff_ the result path is analyzed to be at
    -    the top level (this normalization process is done earlier by
    -    internal_prefix_pathspec()).
    -
    -    Because the prefix for a top-level path is an empty string, thus
    -    add_slash() should return an empty path argument as-is, both for
    -    correctness and avoiding inappropriate memory access.
    +    The add_slash() call could segfault when path argument to it is an empty
    +    string, because it makes an out-of-bounds read to decide if an extra
    +    slash '/' needs to be appended to it.
    +
    +    As add_slash() is used to make sure that a valid pathname to a file in
    +    the given directory can be made by appending a filename after the value
    +    returned from it, if path is an empty string, we want to return it
    +    as-is.  The path to a file "F" in the top-level of the working tree
    +    (i.e. path=="") is formed by appending "F" after "" (i.e. path) without
    +    any slash in between.
    +
    +    So, just like the case where a non-empty path already ends with a slash,
    +    return an empty path as-is.
     
         Reported-by: Jeff King <peff@peff.net>
         Helped-by: Jeff King <peff@peff.net>

 builtin/mv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)


base-commit: a6b4b080e4ef65ebbab73e47c0100b5dc12e104c

Comments

Junio C Hamano Sept. 9, 2022, 10:52 p.m. UTC | #1
Shaoxuan Yuan <shaoxuan.yuan02@gmail.com> writes:

> A possible segfault was introduced in c08830de41 (mv: check if
> <destination> is a SKIP_WORKTREE_DIR, 2022-08-09).

This iteration looks good to me (v1 was sufficiently readable
already but an extra explanation made it easier to grok).

Thanks, will queue and let's merge it to 'next'.
diff mbox series

Patch

diff --git a/builtin/mv.c b/builtin/mv.c
index 2d64c1e80f..3413ad1c9b 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -71,7 +71,7 @@  static const char **internal_prefix_pathspec(const char *prefix,
 static const char *add_slash(const char *path)
 {
 	size_t len = strlen(path);
-	if (path[len - 1] != '/') {
+	if (len && path[len - 1] != '/') {
 		char *with_slash = xmalloc(st_add(len, 2));
 		memcpy(with_slash, path, len);
 		with_slash[len++] = '/';