config: disallow relative include paths from blobs
authorJeff King <peff@peff.net>
Tue, 18 Feb 2014 22:58:52 +0000 (00:58 +0200)
committerJunio C Hamano <gitster@pobox.com>
Wed, 19 Feb 2014 00:12:09 +0000 (16:12 -0800)
When we see a relative config include like:

[include]
path = foo

we make it relative to the containing directory of the file
that contains the snippet. This makes no sense for config
read from a blob, as it is not on the filesystem. Something
like "HEAD:some/path" could have a relative path within the
tree, but:

1. It would not be part of include.path, which explicitly
refers to the filesystem.

2. It would need different parsing rules anyway to
determine that it is a tree path.

The current code just uses the "name" field, which is wrong.
Let's split that into "name" and "path" fields, use the
latter for relative includes, and fill in only the former
for blobs.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
config.c
t/t1305-config-include.sh
index d969a5aefc2bca92938d3fd7f6a507e884ce2b7f..b295310d3c22433b46533a902dd9f4f3e60a2423 100644 (file)
--- a/config.c
+++ b/config.c
@@ -21,6 +21,7 @@ struct config_source {
                } buf;
        } u;
        const char *name;
+       const char *path;
        int die_on_error;
        int linenr;
        int eof;
@@ -97,12 +98,12 @@ static int handle_path_include(const char *path, struct config_include_data *inc
        if (!is_absolute_path(path)) {
                char *slash;
 
-               if (!cf || !cf->name)
+               if (!cf || !cf->path)
                        return error("relative config includes must come from files");
 
-               slash = find_last_dir_sep(cf->name);
+               slash = find_last_dir_sep(cf->path);
                if (slash)
-                       strbuf_add(&buf, cf->name, slash - cf->name + 1);
+                       strbuf_add(&buf, cf->path, slash - cf->path + 1);
                strbuf_addstr(&buf, path);
                path = buf.buf;
        }
@@ -1040,7 +1041,7 @@ int git_config_from_file(config_fn_t fn, const char *filename, void *data)
                struct config_source top;
 
                top.u.file = f;
-               top.name = filename;
+               top.name = top.path = filename;
                top.die_on_error = 1;
                top.do_fgetc = config_file_fgetc;
                top.do_ungetc = config_file_ungetc;
@@ -1062,6 +1063,7 @@ int git_config_from_buf(config_fn_t fn, const char *name, const char *buf,
        top.u.buf.len = len;
        top.u.buf.pos = 0;
        top.name = name;
+       top.path = NULL;
        top.die_on_error = 0;
        top.do_fgetc = config_buf_fgetc;
        top.do_ungetc = config_buf_ungetc;
index a70707620f146d3fce69f77e08cae3a47253f157..6edd38b39a0b758b8007c1d58b858c9e3b533928 100755 (executable)
@@ -122,6 +122,22 @@ test_expect_success 'relative includes from command line fail' '
        test_must_fail git -c include.path=one config test.one
 '
 
+test_expect_success 'absolute includes from blobs work' '
+       echo "[test]one = 1" >one &&
+       echo "[include]path=$(pwd)/one" >blob &&
+       blob=$(git hash-object -w blob) &&
+       echo 1 >expect &&
+       git config --blob=$blob test.one >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'relative includes from blobs fail' '
+       echo "[test]one = 1" >one &&
+       echo "[include]path=one" >blob &&
+       blob=$(git hash-object -w blob) &&
+       test_must_fail git config --blob=$blob test.one
+'
+
 test_expect_success 'include cycles are detected' '
        cat >.gitconfig <<-\EOF &&
        [test]value = gitconfig