Commit 3245896bb7527cb42d48faf68f33858c887f2b3d

Matt Burke 2015-09-10T13:18:26

Add a test for custom header validation Also, *some* custom headers actually are valid.

diff --git a/src/transports/smart.c b/src/transports/smart.c
index b4f8578..8388d9d 100644
--- a/src/transports/smart.c
+++ b/src/transports/smart.c
@@ -66,6 +66,10 @@ static int git_smart__set_callbacks(
 	return 0;
 }
 
+#define forbid_custom_header(disallowed_name) \
+	if (strncmp(disallowed_name, custom_header, name_len) == 0) \
+		return false
+
 bool is_valid_custom_header(const char *custom_header)
 {
 	const char *c;
@@ -91,12 +95,14 @@ bool is_valid_custom_header(const char *custom_header)
 		return false;
 
 	// Disallow headers that we set
-	return git__strncmp("User-Agent", custom_header, name_len) == 0 &&
-		git__strncmp("Host", custom_header, name_len) == 0 &&
-		git__strncmp("Accept", custom_header, name_len) == 0 &&
-		git__strncmp("Content-Type", custom_header, name_len) == 0 &&
-		git__strncmp("Transfer-Encoding", custom_header, name_len) == 0 &&
-		git__strncmp("Content-Length", custom_header, name_len) == 0;
+	forbid_custom_header("User-Agent");
+	forbid_custom_header("Host");
+	forbid_custom_header("Accept");
+	forbid_custom_header("Content-Type");
+	forbid_custom_header("Transfer-Encoding");
+	forbid_custom_header("Content-Length");
+
+	return true;
 }
 
 const char *find_invalid_custom_header(const git_strarray *custom_headers)
diff --git a/tests/online/clone.c b/tests/online/clone.c
index 225b3ab..b84be40 100644
--- a/tests/online/clone.c
+++ b/tests/online/clone.c
@@ -213,6 +213,33 @@ void test_online_clone__custom_remote_callbacks(void)
 	cl_assert(callcount > 0);
 }
 
+void test_online_clone__custom_headers(void)
+{
+	char *empty_header = "";
+	char *unnamed_header = "this is a header about nothing";
+	char *newlines = "X-Custom: almost OK\n";
+	char *conflict = "Accept: defined-by-git";
+	char *ok = "X-Custom: this should be ok";
+
+	g_options.fetch_opts.custom_headers.count = 1;
+
+	g_options.fetch_opts.custom_headers.strings = &empty_header;
+	cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
+
+	g_options.fetch_opts.custom_headers.strings = &unnamed_header;
+	cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
+
+	g_options.fetch_opts.custom_headers.strings = &newlines;
+	cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
+
+	g_options.fetch_opts.custom_headers.strings = &conflict;
+	cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
+
+	/* Finally, we got it right! */
+	g_options.fetch_opts.custom_headers.strings = &ok;
+	cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
+}
+
 static int cred_failure_cb(
 	git_cred **cred,
 	const char *url,