diff options
author | Ben Straub <bs@github.com> | 2013-11-05 11:35:57 -0800 |
---|---|---|
committer | Ben Straub <bs@github.com> | 2013-11-05 11:35:57 -0800 |
commit | 79c443425b1b3d67e8180663c6e80793b587c888 (patch) | |
tree | c46002080c8ee052c038da777c730d1d366e1706 | |
parent | d6eb3f9ce7f3b794d8e9ec2bb52bf995dd32cde9 (diff) | |
download | libgit2-79c443425b1b3d67e8180663c6e80793b587c888.tar.gz |
Make url decoding more bulletproofbetter-url-parsing
-rw-r--r-- | src/netops.c | 19 | ||||
-rw-r--r-- | tests-clar/network/urlparse.c | 4 |
2 files changed, 9 insertions, 14 deletions
diff --git a/src/netops.c b/src/netops.c index ce49116e3..d7f17b1fc 100644 --- a/src/netops.c +++ b/src/netops.c @@ -658,23 +658,18 @@ void gitno_connection_data_free_ptrs(gitno_connection_data *d) git__free(d->pass); d->pass = NULL; } -static char unescape_hex(char *x) -{ - char digit; - digit = ((x[0] >= 'A') ? ((x[0] & 0xdf) - 'A')+10 : (x[0] - '0')); - digit *= 16; - digit += ((x[1] >= 'A') ? ((x[1] & 0xdf) - 'A')+10 : (x[1] - '0')); - return digit; -} - +#define hex2c(c) ((c | 32) % 39 - 9) static char* unescape(char *str) { int x, y; + int len = strlen(str); - for (x=y=0; str[x]; ++x, ++y) { + for (x=y=0; str[y]; ++x, ++y) { if ((str[x] = str[y]) == '%') { - str[x] = unescape_hex(str+y+1); - y += 2; + if (y < len-2 && isxdigit(str[y+1]) && isxdigit(str[y+2])) { + str[x] = (hex2c(str[y+1]) << 4) + hex2c(str[y+2]); + y += 2; + } } } str[x] = '\0'; diff --git a/tests-clar/network/urlparse.c b/tests-clar/network/urlparse.c index 3ec3a51a3..31616275a 100644 --- a/tests-clar/network/urlparse.c +++ b/tests-clar/network/urlparse.c @@ -130,12 +130,12 @@ void test_network_urlparse__connection_data_ssl(void) void test_network_urlparse__encoded_username_password(void) { cl_git_pass(gitno_connection_data_from_url(&conndata, - "https://user%2fname:pass%40word@example.com/foo/bar/baz", "bar/baz")); + "https://user%2fname:pass%40word%zyx%v@example.com/foo/bar/baz", "bar/baz")); cl_assert_equal_s(conndata.host, "example.com"); cl_assert_equal_s(conndata.port, "443"); cl_assert_equal_s(conndata.path, "/foo/"); cl_assert_equal_s(conndata.user, "user/name"); - cl_assert_equal_s(conndata.pass, "pass@word"); + cl_assert_equal_s(conndata.pass, "pass@word%zyx%v"); cl_assert_equal_i(conndata.use_ssl, true); } |