From: Junio C Hamano Date: Tue, 27 Feb 2018 18:34:02 +0000 (-0800) Subject: Merge branch 'jk/sq-dequote-on-bogus-input' X-Git-Tag: v2.17.0-rc0~65 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/5aebb3e0ef7f06358d1ca224247a5fbc12e99ccc?ds=inline;hp=-c Merge branch 'jk/sq-dequote-on-bogus-input' Code to unquote single-quoted string (used in the parser for configuration files, etc.) did not diagnose bogus input correctly and produced bogus results instead. * jk/sq-dequote-on-bogus-input: sq_dequote: fix extra consumption of source string --- 5aebb3e0ef7f06358d1ca224247a5fbc12e99ccc diff --combined quote.c index 37d2686865,5e44671d47..c95dd2cafb --- a/quote.c +++ b/quote.c @@@ -43,22 -43,6 +43,22 @@@ void sq_quote_buf(struct strbuf *dst, c free(to_free); } +void sq_quote_buf_pretty(struct strbuf *dst, const char *src) +{ + static const char ok_punct[] = "+,-./:=@_^"; + const char *p; + + for (p = src; *p; p++) { + if (!isalpha(*p) && !isdigit(*p) && !strchr(ok_punct, *p)) { + sq_quote_buf(dst, src); + return; + } + } + + /* if we get here, we did not need quoting */ + strbuf_addstr(dst, src); +} + void sq_quotef(struct strbuf *dst, const char *fmt, ...) { struct strbuf src = STRBUF_INIT; @@@ -72,7 -56,7 +72,7 @@@ strbuf_release(&src); } -void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen) +void sq_quote_argv(struct strbuf *dst, const char **argv) { int i; @@@ -81,16 -65,8 +81,16 @@@ for (i = 0; argv[i]; ++i) { strbuf_addch(dst, ' '); sq_quote_buf(dst, argv[i]); - if (maxlen && dst->len > maxlen) - die("Too many or long arguments"); + } +} + +void sq_quote_argv_pretty(struct strbuf *dst, const char **argv) +{ + int i; + + for (i = 0; argv[i]; i++) { + strbuf_addch(dst, ' '); + sq_quote_buf_pretty(dst, argv[i]); } } @@@ -118,9 -94,15 +118,15 @@@ static char *sq_dequote_step(char *arg *next = NULL; return arg; case '\\': - c = *++src; - if (need_bs_quote(c) && *++src == '\'') { - *dst++ = c; + /* + * Allow backslashed characters outside of + * single-quotes only if they need escaping, + * and only if we resume the single-quoted part + * afterward. + */ + if (need_bs_quote(src[1]) && src[2] == '\'') { + *dst++ = src[1]; + src += 2; continue; } /* Fallthrough */ @@@ -455,7 -437,6 +461,7 @@@ void tcl_quote_buf(struct strbuf *sb, c case '{': case '}': case '$': case '\\': case '"': strbuf_addch(sb, '\\'); + /* fallthrough */ default: strbuf_addch(sb, c); break; diff --combined t/t1300-repo-config.sh index cbeb9bebee,0158d459c5..4f8e6f5fde --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@@ -901,36 -901,6 +901,36 @@@ test_expect_success 'get --path barfs o test_must_fail git config --get --path path.bool ' +test_expect_success 'get --expiry-date' ' + rel="3.weeks.5.days.00:00" && + rel_out="$rel ->" && + cat >.git/config <<-\EOF && + [date] + valid1 = "3.weeks.5.days 00:00" + valid2 = "Fri Jun 4 15:46:55 2010" + valid3 = "2017/11/11 11:11:11PM" + valid4 = "2017/11/10 09:08:07 PM" + valid5 = "never" + invalid1 = "abc" + EOF + cat >expect <<-EOF && + $(test-date timestamp $rel) + 1275666415 + 1510441871 + 1510348087 + 0 + EOF + { + echo "$rel_out $(git config --expiry-date date.valid1)" + git config --expiry-date date.valid2 && + git config --expiry-date date.valid3 && + git config --expiry-date date.valid4 && + git config --expiry-date date.valid5 + } >actual && + test_cmp expect actual && + test_must_fail git config --expiry-date date.invalid1 +' + cat > expect << EOF [quote] leading = " test" @@@ -1206,6 -1176,29 +1206,29 @@@ test_expect_success 'git -c is not conf GIT_CONFIG_PARAMETERS="" git -c x.one=1 config --list ' + sq="'" + test_expect_success 'detect bogus GIT_CONFIG_PARAMETERS' ' + cat >expect <<-\EOF && + env.one one + env.two two + EOF + GIT_CONFIG_PARAMETERS="${sq}env.one=one${sq} ${sq}env.two=two${sq}" \ + git config --get-regexp "env.*" >actual && + test_cmp expect actual && + + cat >expect <<-EOF && + env.one one${sq} + env.two two + EOF + GIT_CONFIG_PARAMETERS="${sq}env.one=one${sq}\\$sq$sq$sq ${sq}env.two=two${sq}" \ + git config --get-regexp "env.*" >actual && + test_cmp expect actual && + + test_must_fail env \ + GIT_CONFIG_PARAMETERS="${sq}env.one=one${sq}\\$sq ${sq}env.two=two${sq}" \ + git config --get-regexp "env.*" + ' + test_expect_success 'git config --edit works' ' git config -f tmp test.value no && echo test.value=yes >expect &&