Git fork

credential_format(): also encode <host>[:<port>]

An upcoming change wants to sanitize the credential password prompt
where a URL is displayed that may potentially come from a `.gitmodules`
file. To this end, the `credential_format()` function is employed.

To sanitize the host name (and optional port) part of the URL, we need a
new mode of the `strbuf_add_percentencode()` function because the
current mode is both too strict and too lenient: too strict because it
encodes `:`, `[` and `]` (which should be left unencoded in
`<host>:<port>` and in IPv6 addresses), and too lenient because it does
not encode invalid host name characters `/`, `_` and `~`.

So let's introduce and use a new mode specifically to encode the host
name and optional port part of a URI, leaving alpha-numerical
characters, periods, colons and brackets alone and encoding all others.

This only leads to a change of behavior for URLs that contain invalid
host names.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>

+19 -2
+2 -1
credential.c
··· 164 164 strbuf_addch(out, '@'); 165 165 } 166 166 if (c->host) 167 - strbuf_addstr(out, c->host); 167 + strbuf_add_percentencode(out, c->host, 168 + STRBUF_ENCODE_HOST_AND_PORT); 168 169 if (c->path) { 169 170 strbuf_addch(out, '/'); 170 171 strbuf_add_percentencode(out, c->path, 0);
+3 -1
strbuf.c
··· 492 492 unsigned char ch = src[i]; 493 493 if (ch <= 0x1F || ch >= 0x7F || 494 494 (ch == '/' && (flags & STRBUF_ENCODE_SLASH)) || 495 - strchr(URL_UNSAFE_CHARS, ch)) 495 + ((flags & STRBUF_ENCODE_HOST_AND_PORT) ? 496 + !isalnum(ch) && !strchr("-.:[]", ch) : 497 + !!strchr(URL_UNSAFE_CHARS, ch))) 496 498 strbuf_addf(dst, "%%%02X", (unsigned char)ch); 497 499 else 498 500 strbuf_addch(dst, ch);
+1
strbuf.h
··· 380 380 void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src); 381 381 382 382 #define STRBUF_ENCODE_SLASH 1 383 + #define STRBUF_ENCODE_HOST_AND_PORT 2 383 384 384 385 /** 385 386 * Append the contents of a string to a strbuf, percent-encoding any characters
+13
t/t0300-credentials.sh
··· 514 514 EOF 515 515 ' 516 516 517 + test_expect_success 'match percent-encoded values in hostname' ' 518 + test_config "credential.https://a%20b%20c/.helper" "$HELPER" && 519 + check fill <<-\EOF 520 + url=https://a b c/ 521 + -- 522 + protocol=https 523 + host=a b c 524 + username=foo 525 + password=bar 526 + -- 527 + EOF 528 + ' 529 + 517 530 test_expect_success 'fetch with multiple path components' ' 518 531 test_unconfig credential.helper && 519 532 test_config credential.https://example.com/foo/repo.git.helper "verbatim foo bar" &&