config: fix case sensitive subsection names on writing

A user reported a submodule issue regarding a section mix-up, but it could be boiled down to the following test case: $ git init test && cd test $ git config foo."Bar".key test $ git config foo."bar".key test $ tail -n 3 .git/config [foo "Bar"] key = test key = test Sub sections are case sensitive and we have a test for correctly reading them. However we do not have a test for writing out config correctly with case sensitive subsection names, which is why this went unnoticed in 6ae996f2acf (git_config_set: make use of the config parser's event stream, 2018-04-09) Unfortunately we have to make a distinction between old style configuration that looks like [foo.Bar] key = test and the new quoted style as seen above. The old style is documented as case-agnostic, hence we need to keep 'strncasecmp'; although the resulting setting for the old style config differs from the configuration. That will be fixed in a follow up patch. Reported-by: JP Sugarbroad <jpsugar@google.com> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Stefan Beller committed Aug 8, 2018 at 12:50 UTC 2d84f13dcb67762c2506e71232556e196f32600b
2 files changed +12 -1
config.c
+11 -1
@@ -35,6 +35,7 @@ struct config_source {
35 int eof;
36 struct strbuf value;
37 struct strbuf var;
38 + unsigned subsection_case_sensitive : 1;
39
40 int (*do_fgetc)(struct config_source *c);
41 int (*do_ungetc)(int c, struct config_source *conf);
@@ -603,6 +604,7 @@ static int get_value(config_fn_t fn, void *data, struct strbuf *name)
604
605 static int get_extended_base_var(struct strbuf *name, int c)
606 {
607 + cf->subsection_case_sensitive = 0;
608 do {
609 if (c == '\n')
610 goto error_incomplete_line;
@@ -639,6 +641,7 @@ error_incomplete_line:
641
642 static int get_base_var(struct strbuf *name)
643 {
644 + cf->subsection_case_sensitive = 1;
645 for (;;) {
646 int c = get_next_char();
647 if (cf->eof)
@@ -2328,14 +2331,21 @@ static int store_aux_event(enum config_event_t type,
2331 store->parsed[store->parsed_nr].type = type;
2332
2333 if (type == CONFIG_EVENT_SECTION) {
2334 + int (*cmpfn)(const char *, const char *, size_t);
2335 +
2336 if (cf->var.len < 2 || cf->var.buf[cf->var.len - 1] != '.')
2337 return error("invalid section name '%s'", cf->var.buf);
2338
2339 + if (cf->subsection_case_sensitive)
2340 + cmpfn = strncasecmp;
2341 + else
2342 + cmpfn = strncmp;
2343 +
2344 /* Is this the section we were looking for? */
2345 store->is_keys_section =
2346 store->parsed[store->parsed_nr].is_keys_section =
2347 cf->var.len - 1 == store->baselen &&
2338 - !strncasecmp(cf->var.buf, store->key, store->baselen);
2348 + !cmpfn(cf->var.buf, store->key, store->baselen);
2349 if (store->is_keys_section) {
2350 store->section_seen = 1;
2351 ALLOC_GROW(store->seen, store->seen_nr + 1,
t/t1300-config.sh
+1
@@ -1260,6 +1260,7 @@ test_expect_success 'setting different case sensitive subsections ' '
1260 Qc = v2
1261 [d "e"]
1262 f = v1
1263 + [d "E"]
1264 Qf = v2
1265 EOF
1266 # exact match