Commit 79c443425b1b3d67e8180663c6e80793b587c888

Ben Straub 2013-11-05T11:35:57

Make url decoding more bulletproof

diff --git a/src/netops.c b/src/netops.c
index ce49116..d7f17b1 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 3ec3a51..3161627 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);
 }