config: disallow relative include paths from blobs

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>

Jeff King committed Feb 19, 2014 at 00:58 UTC d14d42440d8370f8fe5016a6e212d101745f70cc
2 files changed +22 -4
config.c
+6 -4
@@ -21,6 +21,7 @@ struct config_source {
21 } buf;
22 } u;
23 const char *name;
24 + const char *path;
25 int die_on_error;
26 int linenr;
27 int eof;
@@ -97,12 +98,12 @@ static int handle_path_include(const char *path, struct config_include_data *inc
98 if (!is_absolute_path(path)) {
99 char *slash;
100
100 - if (!cf || !cf->name)
101 + if (!cf || !cf->path)
102 return error("relative config includes must come from files");
103
103 - slash = find_last_dir_sep(cf->name);
104 + slash = find_last_dir_sep(cf->path);
105 if (slash)
105 - strbuf_add(&buf, cf->name, slash - cf->name + 1);
106 + strbuf_add(&buf, cf->path, slash - cf->path + 1);
107 strbuf_addstr(&buf, path);
108 path = buf.buf;
109 }
@@ -1040,7 +1041,7 @@ int git_config_from_file(config_fn_t fn, const char *filename, void *data)
1041 struct config_source top;
1042
1043 top.u.file = f;
1043 - top.name = filename;
1044 + top.name = top.path = filename;
1045 top.die_on_error = 1;
1046 top.do_fgetc = config_file_fgetc;
1047 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,
1063 top.u.buf.len = len;
1064 top.u.buf.pos = 0;
1065 top.name = name;
1066 + top.path = NULL;
1067 top.die_on_error = 0;
1068 top.do_fgetc = config_buf_fgetc;
1069 top.do_ungetc = config_buf_ungetc;
t/t1305-config-include.sh
+16
@@ -122,6 +122,22 @@ test_expect_success 'relative includes from command line fail' '
122 test_must_fail git -c include.path=one config test.one
123 '
124
125 +test_expect_success 'absolute includes from blobs work' '
126 + echo "[test]one = 1" >one &&
127 + echo "[include]path=$(pwd)/one" >blob &&
128 + blob=$(git hash-object -w blob) &&
129 + echo 1 >expect &&
130 + git config --blob=$blob test.one >actual &&
131 + test_cmp expect actual
132 +'
133 +
134 +test_expect_success 'relative includes from blobs fail' '
135 + echo "[test]one = 1" >one &&
136 + echo "[include]path=one" >blob &&
137 + blob=$(git hash-object -w blob) &&
138 + test_must_fail git config --blob=$blob test.one
139 +'
140 +
141 test_expect_success 'include cycles are detected' '
142 cat >.gitconfig <<-\EOF &&
143 [test]value = gitconfig