Skip to content

Commit 9acc591

Browse files
peffgitster
authored andcommitted
config: add a notion of "scope"
A config callback passed to git_config() doesn't know very much about the context in which it sees a variable. It can ask whether the variable comes from a file, and get the file name. But without analyzing the filename (which is hard to do accurately), it cannot tell whether it is in system-level config, user-level config, or repo-specific config. Generally this doesn't matter; the point of not passing this to the callback is that it should treat the config the same no matter where it comes from. But some programs, like upload-pack, are a special case: we should be able to run them in an untrusted repository, which means we cannot use any "dangerous" config from the repository config file (but it is OK to use it from system or user config). This patch teaches the config code to record the "scope" of each variable, and make it available inside config callbacks, similar to how we give access to the filename. The scope is the starting source for a particular parsing operation, and remains the same even if we include other files (so a .git/config which includes another file will remain CONFIG_SCOPE_REPO, as it would be similarly untrusted). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 0d44a2d commit 9acc591

File tree

4 files changed

+53
-0
lines changed

4 files changed

+53
-0
lines changed

cache.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,6 +1604,16 @@ extern const char *get_log_output_encoding(void);
16041604
extern const char *get_commit_output_encoding(void);
16051605

16061606
extern int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
1607+
1608+
enum config_scope {
1609+
CONFIG_SCOPE_UNKNOWN = 0,
1610+
CONFIG_SCOPE_SYSTEM,
1611+
CONFIG_SCOPE_GLOBAL,
1612+
CONFIG_SCOPE_REPO,
1613+
CONFIG_SCOPE_CMDLINE,
1614+
};
1615+
1616+
extern enum config_scope current_config_scope(void);
16071617
extern const char *current_config_origin_type(void);
16081618
extern const char *current_config_name(void);
16091619

@@ -1697,6 +1707,7 @@ struct key_value_info {
16971707
const char *filename;
16981708
int linenr;
16991709
const char *origin_type;
1710+
enum config_scope scope;
17001711
};
17011712

17021713
extern NORETURN void git_die_config(const char *key, const char *err, ...) __attribute__((format(printf, 2, 3)));

config.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ struct config_source {
5757
static struct config_source *cf;
5858
static struct key_value_info *current_config_kvi;
5959

60+
/*
61+
* Similar to the variables above, this gives access to the "scope" of the
62+
* current value (repo, global, etc). For cached values, it can be found via
63+
* the current_config_kvi as above. During parsing, the current value can be
64+
* found in this variable. It's not part of "cf" because it transcends a single
65+
* file (i.e., a file included from .git/config is still in "repo" scope).
66+
*/
67+
static enum config_scope current_parsing_scope;
68+
6069
static int zlib_compression_seen;
6170

6271
/*
@@ -1229,22 +1238,27 @@ static int do_git_config_sequence(config_fn_t fn, void *data)
12291238
char *user_config = expand_user_path("~/.gitconfig");
12301239
char *repo_config = git_pathdup("config");
12311240

1241+
current_parsing_scope = CONFIG_SCOPE_SYSTEM;
12321242
if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0))
12331243
ret += git_config_from_file(fn, git_etc_gitconfig(),
12341244
data);
12351245

1246+
current_parsing_scope = CONFIG_SCOPE_GLOBAL;
12361247
if (xdg_config && !access_or_die(xdg_config, R_OK, ACCESS_EACCES_OK))
12371248
ret += git_config_from_file(fn, xdg_config, data);
12381249

12391250
if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))
12401251
ret += git_config_from_file(fn, user_config, data);
12411252

1253+
current_parsing_scope = CONFIG_SCOPE_REPO;
12421254
if (repo_config && !access_or_die(repo_config, R_OK, 0))
12431255
ret += git_config_from_file(fn, repo_config, data);
12441256

1257+
current_parsing_scope = CONFIG_SCOPE_CMDLINE;
12451258
if (git_config_from_parameters(fn, data) < 0)
12461259
die(_("unable to parse command-line config"));
12471260

1261+
current_parsing_scope = CONFIG_SCOPE_UNKNOWN;
12481262
free(xdg_config);
12491263
free(user_config);
12501264
free(repo_config);
@@ -1383,6 +1397,7 @@ static int configset_add_value(struct config_set *cs, const char *key, const cha
13831397
kv_info->linenr = -1;
13841398
kv_info->origin_type = NULL;
13851399
}
1400+
kv_info->scope = current_parsing_scope;
13861401
si->util = kv_info;
13871402

13881403
return 0;
@@ -2482,3 +2497,11 @@ const char *current_config_name(void)
24822497
die("BUG: current_config_name called outside config callback");
24832498
return name ? name : "";
24842499
}
2500+
2501+
enum config_scope current_config_scope(void)
2502+
{
2503+
if (current_config_kvi)
2504+
return current_config_kvi->scope;
2505+
else
2506+
return current_parsing_scope;
2507+
}

t/helper/test-config.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,21 @@
3535
*
3636
*/
3737

38+
static const char *scope_name(enum config_scope scope)
39+
{
40+
switch (scope) {
41+
case CONFIG_SCOPE_SYSTEM:
42+
return "system";
43+
case CONFIG_SCOPE_GLOBAL:
44+
return "global";
45+
case CONFIG_SCOPE_REPO:
46+
return "repo";
47+
case CONFIG_SCOPE_CMDLINE:
48+
return "cmdline";
49+
default:
50+
return "unknown";
51+
}
52+
}
3853
static int iterate_cb(const char *var, const char *value, void *data)
3954
{
4055
static int nr;
@@ -46,6 +61,7 @@ static int iterate_cb(const char *var, const char *value, void *data)
4661
printf("value=%s\n", value ? value : "(null)");
4762
printf("origin=%s\n", current_config_origin_type());
4863
printf("name=%s\n", current_config_name());
64+
printf("scope=%s\n", scope_name(current_config_scope()));
4965

5066
return 0;
5167
}

t/t1308-config-set.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,16 +238,19 @@ test_expect_success 'iteration shows correct origins' '
238238
value=from-home
239239
origin=file
240240
name=$(pwd)/.gitconfig
241+
scope=global
241242
242243
key=foo.bar
243244
value=from-repo
244245
origin=file
245246
name=.git/config
247+
scope=repo
246248
247249
key=foo.bar
248250
value=from-cmdline
249251
origin=command line
250252
name=
253+
scope=cmdline
251254
EOF
252255
GIT_CONFIG_PARAMETERS=$cmdline_config test-config iterate >actual &&
253256
test_cmp expect actual

0 commit comments

Comments
 (0)