mailinfo: do not get confused with logical lines that are too long.
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 26 Feb 2007 19:10:59 +0000 (11:10 -0800)
committerJunio C Hamano <junkio@cox.net>
Tue, 27 Feb 2007 09:02:32 +0000 (01:02 -0800)
It basically considers all the continuation lines to be lines of their
own, and if the total line is bigger than what we can fit in it, we just
truncate the result rather than stop in the middle and then get confused
when we try to parse the "next" line (which is just the remainder of the
first line).

[jc: added test, and tightened boundary a bit per list discussion.]

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
builtin-mailinfo.c
t/t5100-mailinfo.sh
t/t5100/info0006 [new file with mode: 0644]
t/t5100/msg0006 [new file with mode: 0644]
t/t5100/patch0006 [new file with mode: 0644]
t/t5100/sample.mbox

index 583da38b6750185eb38f04d91555aa75ee4a77b0..cf5ef29c0fa524799675734a3b4355ab326c76aa 100644 (file)
@@ -406,6 +406,11 @@ static int is_rfc2822_header(char *line)
         */
        int ch;
        char *cp = line;
+
+       /* Count mbox From headers as headers */
+       if (!memcmp(line, "From ", 5) || !memcmp(line, ">From ", 6))
+               return 1;
+
        while ((ch = *cp++)) {
                if (ch == ':')
                        return cp != line;
@@ -417,30 +422,61 @@ static int is_rfc2822_header(char *line)
        return 0;
 }
 
+/*
+ * sz is size of 'line' buffer in bytes.  Must be reasonably
+ * long enough to hold one physical real-world e-mail line.
+ */
 static int read_one_header_line(char *line, int sz, FILE *in)
 {
-       int ofs = 0;
-       while (ofs < sz) {
-               int peek, len;
-               if (fgets(line + ofs, sz - ofs, in) == NULL)
-                       break;
-               len = eatspace(line + ofs);
-               if ((len == 0) || !is_rfc2822_header(line)) {
-                       /* Re-add the newline */
-                       line[ofs + len] = '\n';
-                       line[ofs + len + 1] = '\0';
-                       break;
-               }
-               ofs += len;
-               /* Yuck, 2822 header "folding" */
+       int len;
+
+       /*
+        * We will read at most (sz-1) bytes and then potentially
+        * re-add NUL after it.  Accessing line[sz] after this is safe
+        * and we can allow len to grow up to and including sz.
+        */
+       sz--;
+
+       /* Get the first part of the line. */
+       if (!fgets(line, sz, in))
+               return 0;
+
+       /*
+        * Is it an empty line or not a valid rfc2822 header?
+        * If so, stop here, and return false ("not a header")
+        */
+       len = eatspace(line);
+       if (!len || !is_rfc2822_header(line)) {
+               /* Re-add the newline */
+               line[len] = '\n';
+               line[len + 1] = '\0';
+               return 0;
+       }
+
+       /*
+        * Now we need to eat all the continuation lines..
+        * Yuck, 2822 header "folding"
+        */
+       for (;;) {
+               int peek, addlen;
+               static char continuation[1000];
+
                peek = fgetc(in); ungetc(peek, in);
                if (peek != ' ' && peek != '\t')
                        break;
+               if (!fgets(continuation, sizeof(continuation), in))
+                       break;
+               addlen = eatspace(continuation);
+               if (len < sz - 1) {
+                       if (addlen >= sz - len)
+                               addlen = sz - len - 1;
+                       memcpy(line + len, continuation, addlen);
+                       len += addlen;
+               }
        }
-       /* Count mbox From headers as headers */
-       if (!ofs && (!memcmp(line, "From ", 5) || !memcmp(line, ">From ", 6)))
-               ofs = 1;
-       return ofs;
+       line[len] = 0;
+
+       return 1;
 }
 
 static int decode_q_segment(char *in, char *ot, char *ep, int rfc2047)
index 17c1b80b5bef863a62b533153ed91e17e47f1a72..4d2b781a1877b2718b961a057b0dddea8f87c51b 100755 (executable)
@@ -11,7 +11,7 @@ test_expect_success 'split sample box' \
        'git-mailsplit -o. ../t5100/sample.mbox >last &&
        last=`cat last` &&
        echo total is $last &&
-       test `cat last` = 5'
+       test `cat last` = 6'
 
 for mail in `echo 00*`
 do
diff --git a/t/t5100/info0006 b/t/t5100/info0006
new file mode 100644 (file)
index 0000000..8c05277
--- /dev/null
@@ -0,0 +1,5 @@
+Author: A U Thor
+Email: a.u.thor@example.com
+Subject: a commit.
+Date: Fri, 9 Jun 2006 00:44:16 -0700
+
diff --git a/t/t5100/msg0006 b/t/t5100/msg0006
new file mode 100644 (file)
index 0000000..b275a9a
--- /dev/null
@@ -0,0 +1,2 @@
+Here is a patch from A U Thor.
+
diff --git a/t/t5100/patch0006 b/t/t5100/patch0006
new file mode 100644 (file)
index 0000000..8ce1551
--- /dev/null
@@ -0,0 +1,14 @@
+---
+ foo |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/foo b/foo
+index 9123cdc..918dcf8 100644
+--- a/foo
++++ b/foo
+@@ -1 +1 @@
+-Fri Jun  9 00:44:04 PDT 2006
++Fri Jun  9 00:44:13 PDT 2006
+-- 
+1.4.0.g6f2b
+
index a76845465a4dc26460e7614bf1a2d12058f91799..86bfc27147f7df8458f32fee5a9aa199a0c76b3a 100644 (file)
@@ -315,3 +315,74 @@ To unsubscribe from this list: send the line "unsubscribe git" in
 the body of a message to majordomo@vger.kernel.org
 More majordomo info at  http://vger.kernel.org/majordomo-info.html
 
+From nobody Mon Sep 17 00:00:00 2001
+From: A U Thor <a.u.thor@example.com>
+References: <Pine.LNX.4.640.0001@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0002@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0003@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0004@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0005@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0006@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0007@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0008@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0009@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0010@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0011@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0012@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0013@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0014@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0015@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0016@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0017@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0018@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0019@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0020@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0021@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0022@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0023@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0024@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0025@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0026@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0027@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0028@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0029@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0030@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0031@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0032@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0033@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0034@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0035@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0036@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0037@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0038@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0039@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0040@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0041@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0042@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0043@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0044@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0045@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0046@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0047@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0048@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0049@woody.linux-foundation.org>
+ <Pine.LNX.4.640.0050@woody.linux-foundation.org>
+Date: Fri, 9 Jun 2006 00:44:16 -0700
+Subject: [PATCH] a commit.
+
+Here is a patch from A U Thor.
+
+---
+ foo |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/foo b/foo
+index 9123cdc..918dcf8 100644
+--- a/foo
++++ b/foo
+@@ -1 +1 @@
+-Fri Jun  9 00:44:04 PDT 2006
++Fri Jun  9 00:44:13 PDT 2006
+-- 
+1.4.0.g6f2b
+