Revise custom header error messages If the header doesn't look like a header (e.g. if it doesn't have a ":" or if it has newlines), report "custom HTTP header '%s' is malformed". If the header has the same name as a header already set by libgit2 (e.g. "Host"), report "HTTP header '%s' is already set by libgit2".
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
diff --git a/src/transports/smart.c b/src/transports/smart.c
index fc7630c..f0f212c 100644
--- a/src/transports/smart.c
+++ b/src/transports/smart.c
@@ -66,57 +66,55 @@ static int git_smart__set_callbacks(
return 0;
}
-static char *forbidden_custom_headers[] = {
- "User-Agent",
- "Host",
- "Accept",
- "Content-Type",
- "Transfer-Encoding",
- "Content-Length",
-};
+int http_header_name_length(const char *http_header)
+{
+ const char *colon = strchr(http_header, ':');
+ if (!colon)
+ return 0;
+ return colon - http_header;
+}
-bool is_valid_custom_header(const char *custom_header)
+bool is_malformed_http_header(const char *http_header)
{
const char *c;
int name_len;
- unsigned long i;
// Disallow \r and \n
- c = strchr(custom_header, '\r');
- if (c != NULL)
- return false;
- c = strchr(custom_header, '\n');
- if (c != NULL)
- return false;
+ c = strchr(http_header, '\r');
+ if (c)
+ return true;
+ c = strchr(http_header, '\n');
+ if (c)
+ return true;
// Require a header name followed by :
- c = strchr(custom_header, ':');
- if (c == NULL)
- return false;
- name_len = c - custom_header;
+ name_len = http_header_name_length(http_header);
if (name_len < 1)
- return false;
-
- // Disallow headers that we set
- for (i = 0; i < ARRAY_SIZE(forbidden_custom_headers); i++)
- if (strncmp(forbidden_custom_headers[i], custom_header, name_len) == 0)
- return false;
+ return true;
- return true;
+ return false;
}
-const char *find_invalid_custom_header(const git_strarray *custom_headers)
-{
- size_t i;
+static char *forbidden_custom_headers[] = {
+ "User-Agent",
+ "Host",
+ "Accept",
+ "Content-Type",
+ "Transfer-Encoding",
+ "Content-Length",
+};
- if (custom_headers == NULL || custom_headers->count == 0)
- return NULL;
+bool is_forbidden_custom_header(const char *custom_header)
+{
+ unsigned long i;
+ int name_len = http_header_name_length(custom_header);
- for (i = 0; i < custom_headers->count; i++)
- if (!is_valid_custom_header(custom_headers->strings[i]))
- return custom_headers->strings[i];
+ // Disallow headers that we set
+ for (i = 0; i < ARRAY_SIZE(forbidden_custom_headers); i++)
+ if (strncmp(forbidden_custom_headers[i], custom_header, name_len) == 0)
+ return true;
- return NULL;
+ return false;
}
static int git_smart__set_custom_headers(
@@ -124,11 +122,17 @@ static int git_smart__set_custom_headers(
const git_strarray *custom_headers)
{
transport_smart *t = (transport_smart *)transport;
- const char *invalid_header = find_invalid_custom_header(custom_headers);
+ size_t i;
- if (invalid_header != NULL) {
- giterr_set(GITERR_INVALID, "Illegal HTTP header '%s'", invalid_header);
- return -1;
+ for (i = 0; i < custom_headers->count; i++) {
+ if (is_malformed_http_header(custom_headers->strings[i])) {
+ giterr_set(GITERR_INVALID, "custom HTTP header '%s' is malformed", custom_headers->strings[i]);
+ return -1;
+ }
+ if (is_forbidden_custom_header(custom_headers->strings[i])) {
+ giterr_set(GITERR_INVALID, "custom HTTP header '%s' is already set by libgit2", custom_headers->strings[i]);
+ return -1;
+ }
}
t->custom_headers = custom_headers;