config: really keep value-internal whitespace verbatim

Fix a bug in function parse_value() that prevented whitespace characters (i.e. spaces and horizontal tabs) found inside configuration option values from being parsed and returned in their original form. The bug caused any number of consecutive whitespace characters to be wrongly "squashed" into the same number of space characters. This bug was introduced back in July 2009, in commit ebdaae372b46 ("config: Keep inner whitespace verbatim"). Further investigation showed that setting a configuration value, by invoking git-config(1), converts value-internal horizontal tabs into "\t" escape sequences, which the buggy value-parsing logic in function parse_value() didn't "squash" into spaces. That's why the test included in the ebdaae37 commit passed, which presumably made the bug remain undetected for this long. On the other hand, value-internal literal horizontal tab characters, found in a configuration file edited by hand, do get "squashed" by the value-parsing logic, so the right choice was to fix this bug by making the value-internal whitespace characters preserved verbatim. Signed-off-by: Dragan Simic <dsimic@manjaro.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Dragan Simic committed Mar 21, 2024 at 07:06 UTC f0b894443040cb222fbd80d9661cfa7583a9164f
1 file changed +9 -4
config.c
+9 -4
@@ -819,7 +819,8 @@ static int get_next_char(struct config_source *cs)
819
820 static char *parse_value(struct config_source *cs)
821 {
822 - int quote = 0, comment = 0, space = 0;
822 + int quote = 0, comment = 0;
823 + size_t trim_len = 0;
824
825 strbuf_reset(&cs->value);
826 for (;;) {
@@ -829,13 +830,17 @@ static char *parse_value(struct config_source *cs)
830 cs->linenr--;
831 return NULL;
832 }
833 + if (trim_len)
834 + strbuf_setlen(&cs->value, trim_len);
835 return cs->value.buf;
836 }
837 if (comment)
838 continue;
839 if (isspace(c) && !quote) {
840 + if (!trim_len)
841 + trim_len = cs->value.len;
842 if (cs->value.len)
838 - space++;
843 + strbuf_addch(&cs->value, c);
844 continue;
845 }
846 if (!quote) {
@@ -844,8 +849,8 @@ static char *parse_value(struct config_source *cs)
849 continue;
850 }
851 }
847 - for (; space; space--)
848 - strbuf_addch(&cs->value, ' ');
852 + if (trim_len)
853 + trim_len = 0;
854 if (c == '\\') {
855 c = get_next_char(cs);
856 switch (c) {