aboutsummaryrefslogtreecommitdiff
path: root/mailinfo.c
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2006-05-26 00:46:58 -0700
committerJunio C Hamano <junkio@cox.net>2006-05-26 00:49:36 -0700
commitef29c11702594e616cf43bea260515d9f14f17b0 (patch)
tree6334bff1bd9de619037858439b8abbd16569ab0f /mailinfo.c
parent2dec02b1ecafc47d4031d0a68a94c775a6a9ff9e (diff)
downloadgit-ef29c11702594e616cf43bea260515d9f14f17b0.tar.gz
git-ef29c11702594e616cf43bea260515d9f14f17b0.tar.xz
mailinfo: More carefully parse header lines in read_one_header_line()
We exited prematurely from header parsing loop when the header field did not have a space after the colon but we insisted on it, and we got the check wrong because we forgot that we strip the trailing whitespace before we do the check. The space after the colon is not even required by RFC2822, so stop requiring it. While we are at it, the header line is specified to be more strict than "anything with a colon in it" (there must be one or more characters before the colon, and they must not be controls, SP or non US-ASCII), so implement that check as well, lest we mistakenly think something like: Bogus not a header line: this is not. as a header line. Signed-off-by: Junio C Hamano <junkio@cox.net>
Diffstat (limited to 'mailinfo.c')
-rw-r--r--mailinfo.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/mailinfo.c b/mailinfo.c
index 241bfb9e2..88f9fbb19 100644
--- a/mailinfo.c
+++ b/mailinfo.c
@@ -382,19 +382,40 @@ static void check_header_line(char *line)
check_header(line, header);
}
+static int is_rfc2822_header(char *line)
+{
+ /*
+ * The section that defines the loosest possible
+ * field name is "3.6.8 Optional fields".
+ *
+ * optional-field = field-name ":" unstructured CRLF
+ * field-name = 1*ftext
+ * ftext = %d33-57 / %59-126
+ */
+ int ch;
+ char *cp = line;
+ while ((ch = *cp++)) {
+ if (ch == ':')
+ return cp != line;
+ if ((33 <= ch && ch <= 57) ||
+ (59 <= ch && ch <= 126))
+ continue;
+ break;
+ }
+ return 0;
+}
+
static int read_one_header_line(char *line, int sz, FILE *in)
{
int ofs = 0;
while (ofs < sz) {
- const char *colon;
int peek, len;
if (fgets(line + ofs, sz - ofs, in) == NULL)
break;
len = eatspace(line + ofs);
if (len == 0)
break;
- colon = strchr(line, ':');
- if (!colon || !isspace(colon[1])) {
+ if (!is_rfc2822_header(line)) {
/* Re-add the newline */
line[ofs + len] = '\n';
line[ofs + len + 1] = '\0';