Skip to content

Commit b44d011

Browse files
bk2204gitster
authored andcommitted
credential: fix matching URLs with multiple levels in path
46fd7b3 ("credential: allow wildcard patterns when matching config", 2020-02-20) introduced support for matching credential helpers using urlmatch. In doing so, it introduced code to percent-encode the paths we get from the credential helper so that they could be effectively matched by the urlmatch code. Unfortunately, that code had a bug: it percent-encoded the slashes in the path, resulting in any URL path that contained multiple levels (i.e., a directory component) not matching. We are currently the only caller of the percent-encoding code and could simply change it not to encode slashes. However, we still want to encode slashes in the username component, so we need to have both behaviors available. So instead, let's add a flag to control encoding slashes, which is the behavior we want here, and use it when calling the code in this case. Add a test for credential helper URLs using multiple slashes in the path, which our test suite previously lacked, as well as one ensuring that we handle usernames with slashes gracefully. Since we're testing other percent-encoding handling, let's add one for non-ASCII UTF-8 characters as well. Reported-by: Ilya Tretyakov <[email protected]> Signed-off-by: Carlo Marcelo Arenas Belón <[email protected]> Signed-off-by: brian m. carlson <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 46fd7b3 commit b44d011

File tree

4 files changed

+58
-6
lines changed

4 files changed

+58
-6
lines changed

credential.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,14 +131,14 @@ static void credential_format(struct credential *c, struct strbuf *out)
131131
return;
132132
strbuf_addf(out, "%s://", c->protocol);
133133
if (c->username && *c->username) {
134-
strbuf_add_percentencode(out, c->username);
134+
strbuf_add_percentencode(out, c->username, STRBUF_ENCODE_SLASH);
135135
strbuf_addch(out, '@');
136136
}
137137
if (c->host)
138138
strbuf_addstr(out, c->host);
139139
if (c->path) {
140140
strbuf_addch(out, '/');
141-
strbuf_add_percentencode(out, c->path);
141+
strbuf_add_percentencode(out, c->path, 0);
142142
}
143143
}
144144

strbuf.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -479,15 +479,17 @@ void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src)
479479
}
480480
}
481481

482-
#define URL_UNSAFE_CHARS " <>\"%{}|\\^`:/?#[]@!$&'()*+,;="
482+
#define URL_UNSAFE_CHARS " <>\"%{}|\\^`:?#[]@!$&'()*+,;="
483483

484-
void strbuf_add_percentencode(struct strbuf *dst, const char *src)
484+
void strbuf_add_percentencode(struct strbuf *dst, const char *src, int flags)
485485
{
486486
size_t i, len = strlen(src);
487487

488488
for (i = 0; i < len; i++) {
489489
unsigned char ch = src[i];
490-
if (ch <= 0x1F || ch >= 0x7F || strchr(URL_UNSAFE_CHARS, ch))
490+
if (ch <= 0x1F || ch >= 0x7F ||
491+
(ch == '/' && (flags & STRBUF_ENCODE_SLASH)) ||
492+
strchr(URL_UNSAFE_CHARS, ch))
491493
strbuf_addf(dst, "%%%02X", (unsigned char)ch);
492494
else
493495
strbuf_addch(dst, ch);

strbuf.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,11 +366,16 @@ size_t strbuf_expand_dict_cb(struct strbuf *sb,
366366
*/
367367
void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src);
368368

369+
#define STRBUF_ENCODE_SLASH 1
370+
369371
/**
370372
* Append the contents of a string to a strbuf, percent-encoding any characters
371373
* that are needed to be encoded for a URL.
374+
*
375+
* If STRBUF_ENCODE_SLASH is set in flags, percent-encode slashes. Otherwise,
376+
* slashes are not percent-encoded.
372377
*/
373-
void strbuf_add_percentencode(struct strbuf *dst, const char *src);
378+
void strbuf_add_percentencode(struct strbuf *dst, const char *src, int flags);
374379

375380
/**
376381
* Append the given byte size as a human-readable string (i.e. 12.23 KiB,

t/t0300-credentials.sh

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,51 @@ test_expect_success 'match percent-encoded values' '
291291
EOF
292292
'
293293

294+
test_expect_success 'match percent-encoded UTF-8 values in path' '
295+
test_config credential.https://example.com.useHttpPath true &&
296+
test_config credential.https://example.com/perú.git.helper "$HELPER" &&
297+
check fill <<-\EOF
298+
url=https://example.com/per%C3%BA.git
299+
--
300+
protocol=https
301+
host=example.com
302+
path=perú.git
303+
username=foo
304+
password=bar
305+
--
306+
EOF
307+
'
308+
309+
test_expect_success 'match percent-encoded values in username' '
310+
test_config credential.https://user%[email protected]/foo/bar.git.helper "$HELPER" &&
311+
check fill <<-\EOF
312+
url=https://user%[email protected]/foo/bar.git
313+
--
314+
protocol=https
315+
host=example.com
316+
username=foo
317+
password=bar
318+
--
319+
EOF
320+
'
321+
322+
test_expect_success 'fetch with multiple path components' '
323+
test_unconfig credential.helper &&
324+
test_config credential.https://example.com/foo/repo.git.helper "verbatim foo bar" &&
325+
check fill <<-\EOF
326+
url=https://example.com/foo/repo.git
327+
--
328+
protocol=https
329+
host=example.com
330+
username=foo
331+
password=bar
332+
--
333+
verbatim: get
334+
verbatim: protocol=https
335+
verbatim: host=example.com
336+
EOF
337+
'
338+
294339
test_expect_success 'pull username from config' '
295340
test_config credential.https://example.com.username foo &&
296341
check fill <<-\EOF

0 commit comments

Comments
 (0)