提交 cc26efb3 编写于 作者: J Junio C Hamano

Merge branch 'js/mailinfo'

* js/mailinfo:
  mailsplit: minor clean-up in read_line_with_nul()
  mailinfo: apply the same fix not to lose NULs in BASE64 and QP codepaths
  mailsplit and mailinfo: gracefully handle NUL characters
...@@ -434,6 +434,7 @@ static int read_one_header_line(char *line, int sz, FILE *in) ...@@ -434,6 +434,7 @@ static int read_one_header_line(char *line, int sz, FILE *in)
static int decode_q_segment(char *in, char *ot, unsigned otsize, char *ep, int rfc2047) static int decode_q_segment(char *in, char *ot, unsigned otsize, char *ep, int rfc2047)
{ {
char *otbegin = ot;
char *otend = ot + otsize; char *otend = ot + otsize;
int c; int c;
while ((c = *in++) != 0 && (in <= ep)) { while ((c = *in++) != 0 && (in <= ep)) {
...@@ -453,13 +454,14 @@ static int decode_q_segment(char *in, char *ot, unsigned otsize, char *ep, int r ...@@ -453,13 +454,14 @@ static int decode_q_segment(char *in, char *ot, unsigned otsize, char *ep, int r
*ot++ = c; *ot++ = c;
} }
*ot = 0; *ot = 0;
return 0; return (ot - otbegin);
} }
static int decode_b_segment(char *in, char *ot, unsigned otsize, char *ep) static int decode_b_segment(char *in, char *ot, unsigned otsize, char *ep)
{ {
/* Decode in..ep, possibly in-place to ot */ /* Decode in..ep, possibly in-place to ot */
int c, pos = 0, acc = 0; int c, pos = 0, acc = 0;
char *otbegin = ot;
char *otend = ot + otsize; char *otend = ot + otsize;
while ((c = *in++) != 0 && (in <= ep)) { while ((c = *in++) != 0 && (in <= ep)) {
...@@ -505,7 +507,7 @@ static int decode_b_segment(char *in, char *ot, unsigned otsize, char *ep) ...@@ -505,7 +507,7 @@ static int decode_b_segment(char *in, char *ot, unsigned otsize, char *ep)
} }
} }
*ot = 0; *ot = 0;
return 0; return (ot - otbegin);
} }
/* /*
...@@ -623,25 +625,24 @@ static void decode_header(char *it, unsigned itsize) ...@@ -623,25 +625,24 @@ static void decode_header(char *it, unsigned itsize)
convert_to_utf8(it, itsize, ""); convert_to_utf8(it, itsize, "");
} }
static void decode_transfer_encoding(char *line, unsigned linesize) static int decode_transfer_encoding(char *line, unsigned linesize, int inputlen)
{ {
char *ep; char *ep;
switch (transfer_encoding) { switch (transfer_encoding) {
case TE_QP: case TE_QP:
ep = line + strlen(line); ep = line + inputlen;
decode_q_segment(line, line, linesize, ep, 0); return decode_q_segment(line, line, linesize, ep, 0);
break;
case TE_BASE64: case TE_BASE64:
ep = line + strlen(line); ep = line + inputlen;
decode_b_segment(line, line, linesize, ep); return decode_b_segment(line, line, linesize, ep);
break;
case TE_DONTCARE: case TE_DONTCARE:
break; default:
return inputlen;
} }
} }
static int handle_filter(char *line, unsigned linesize); static int handle_filter(char *line, unsigned linesize, int linelen);
static int find_boundary(void) static int find_boundary(void)
{ {
...@@ -669,7 +670,7 @@ static int handle_boundary(void) ...@@ -669,7 +670,7 @@ static int handle_boundary(void)
"can't recover\n"); "can't recover\n");
exit(1); exit(1);
} }
handle_filter(newline, sizeof(newline)); handle_filter(newline, sizeof(newline), strlen(newline));
/* skip to the next boundary */ /* skip to the next boundary */
if (!find_boundary()) if (!find_boundary())
...@@ -759,14 +760,14 @@ static int handle_commit_msg(char *line, unsigned linesize) ...@@ -759,14 +760,14 @@ static int handle_commit_msg(char *line, unsigned linesize)
return 0; return 0;
} }
static int handle_patch(char *line) static int handle_patch(char *line, int len)
{ {
fputs(line, patchfile); fwrite(line, 1, len, patchfile);
patch_lines++; patch_lines++;
return 0; return 0;
} }
static int handle_filter(char *line, unsigned linesize) static int handle_filter(char *line, unsigned linesize, int linelen)
{ {
static int filter = 0; static int filter = 0;
...@@ -779,7 +780,7 @@ static int handle_filter(char *line, unsigned linesize) ...@@ -779,7 +780,7 @@ static int handle_filter(char *line, unsigned linesize)
break; break;
filter++; filter++;
case 1: case 1:
if (!handle_patch(line)) if (!handle_patch(line, linelen))
break; break;
filter++; filter++;
default: default:
...@@ -794,6 +795,7 @@ static void handle_body(void) ...@@ -794,6 +795,7 @@ static void handle_body(void)
int rc = 0; int rc = 0;
static char newline[2000]; static char newline[2000];
static char *np = newline; static char *np = newline;
int len = strlen(line);
/* Skip up to the first boundary */ /* Skip up to the first boundary */
if (content_top->boundary) { if (content_top->boundary) {
...@@ -805,16 +807,19 @@ static void handle_body(void) ...@@ -805,16 +807,19 @@ static void handle_body(void)
/* process any boundary lines */ /* process any boundary lines */
if (content_top->boundary && is_multipart_boundary(line)) { if (content_top->boundary && is_multipart_boundary(line)) {
/* flush any leftover */ /* flush any leftover */
if ((transfer_encoding == TE_BASE64) && if (np != newline)
(np != newline)) { handle_filter(newline, sizeof(newline),
handle_filter(newline, sizeof(newline)); np - newline);
}
if (!handle_boundary()) if (!handle_boundary())
return; return;
} }
/* Unwrap transfer encoding */ /* Unwrap transfer encoding */
decode_transfer_encoding(line, sizeof(line)); len = decode_transfer_encoding(line, sizeof(line), len);
if (len < 0) {
error("Malformed input line");
return;
}
switch (transfer_encoding) { switch (transfer_encoding) {
case TE_BASE64: case TE_BASE64:
...@@ -824,39 +829,40 @@ static void handle_body(void) ...@@ -824,39 +829,40 @@ static void handle_body(void)
/* binary data most likely doesn't have newlines */ /* binary data most likely doesn't have newlines */
if (message_type != TYPE_TEXT) { if (message_type != TYPE_TEXT) {
rc = handle_filter(line, sizeof(newline)); rc = handle_filter(line, sizeof(line), len);
break; break;
} }
/* this is a decoded line that may contain /*
* This is a decoded line that may contain
* multiple new lines. Pass only one chunk * multiple new lines. Pass only one chunk
* at a time to handle_filter() * at a time to handle_filter()
*/ */
do { do {
while (*op != '\n' && *op != 0) while (op < line + len && *op != '\n')
*np++ = *op++; *np++ = *op++;
*np = *op; *np = *op;
if (*np != 0) { if (*np != 0) {
/* should be sitting on a new line */ /* should be sitting on a new line */
*(++np) = 0; *(++np) = 0;
op++; op++;
rc = handle_filter(newline, sizeof(newline)); rc = handle_filter(newline, sizeof(newline), np - newline);
np = newline; np = newline;
} }
} while (*op != 0); } while (op < line + len);
/* the partial chunk is saved in newline and /*
* will be appended by the next iteration of fgets * The partial chunk is saved in newline and will be
* appended by the next iteration of read_line_with_nul().
*/ */
break; break;
} }
default: default:
rc = handle_filter(line, sizeof(newline)); rc = handle_filter(line, sizeof(line), len);
} }
if (rc) if (rc)
/* nothing left to filter */ /* nothing left to filter */
break; break;
} while (fgets(line, sizeof(line), fin)); } while ((len = read_line_with_nul(line, sizeof(line), fin)));
return; return;
} }
......
...@@ -45,6 +45,24 @@ static int is_from_line(const char *line, int len) ...@@ -45,6 +45,24 @@ static int is_from_line(const char *line, int len)
/* Could be as small as 64, enough to hold a Unix "From " line. */ /* Could be as small as 64, enough to hold a Unix "From " line. */
static char buf[4096]; static char buf[4096];
/* We cannot use fgets() because our lines can contain NULs */
int read_line_with_nul(char *buf, int size, FILE *in)
{
int len = 0, c;
for (;;) {
c = getc(in);
if (c == EOF)
break;
buf[len++] = c;
if (c == '\n' || len + 1 >= size)
break;
}
buf[len] = '\0';
return len;
}
/* Called with the first line (potentially partial) /* Called with the first line (potentially partial)
* already in buf[] -- normally that should begin with * already in buf[] -- normally that should begin with
* the Unix "From " line. Write it into the specified * the Unix "From " line. Write it into the specified
...@@ -70,19 +88,19 @@ static int split_one(FILE *mbox, const char *name, int allow_bare) ...@@ -70,19 +88,19 @@ static int split_one(FILE *mbox, const char *name, int allow_bare)
* "From " and having something that looks like a date format. * "From " and having something that looks like a date format.
*/ */
for (;;) { for (;;) {
int is_partial = (buf[len-1] != '\n'); int is_partial = len && buf[len-1] != '\n';
if (fputs(buf, output) == EOF) if (fwrite(buf, 1, len, output) != len)
die("cannot write output"); die("cannot write output");
if (fgets(buf, sizeof(buf), mbox) == NULL) { len = read_line_with_nul(buf, sizeof(buf), mbox);
if (len == 0) {
if (feof(mbox)) { if (feof(mbox)) {
status = 1; status = 1;
break; break;
} }
die("cannot read mbox"); die("cannot read mbox");
} }
len = strlen(buf);
if (!is_partial && !is_bare && is_from_line(buf, len)) if (!is_partial && !is_bare && is_from_line(buf, len))
break; /* done with one message */ break; /* done with one message */
} }
......
...@@ -9,6 +9,7 @@ extern const char git_usage_string[]; ...@@ -9,6 +9,7 @@ extern const char git_usage_string[];
extern void list_common_cmds_help(void); extern void list_common_cmds_help(void);
extern void help_unknown_cmd(const char *cmd); extern void help_unknown_cmd(const char *cmd);
extern void prune_packed_objects(int); extern void prune_packed_objects(int);
extern int read_line_with_nul(char *buf, int size, FILE *file);
extern int cmd_add(int argc, const char **argv, const char *prefix); extern int cmd_add(int argc, const char **argv, const char *prefix);
extern int cmd_annotate(int argc, const char **argv, const char *prefix); extern int cmd_annotate(int argc, const char **argv, const char *prefix);
......
...@@ -25,4 +25,22 @@ do ...@@ -25,4 +25,22 @@ do
diff ../t5100/info$mail info$mail" diff ../t5100/info$mail info$mail"
done done
test_expect_success 'respect NULs' '
git mailsplit -d3 -o. ../t5100/nul &&
cmp ../t5100/nul 001 &&
(cat 001 | git mailinfo msg patch) &&
test 4 = $(wc -l < patch)
'
test_expect_success 'Preserve NULs out of MIME encoded message' '
git mailsplit -d5 -o. ../t5100/nul-b64.in &&
cmp ../t5100/nul-b64.in 00001 &&
git mailinfo msg patch <00001 &&
cmp ../t5100/nul-b64.expect patch
'
test_done test_done
文件已添加
From 667d8940e719cddee1cfe237cbbe215e20270b09 Mon Sep 17 00:00:00 2001
From: Junio C Hamano <gitster@pobox.com>
Date: Sun, 25 May 2008 00:38:18 -0700
Subject: [PATCH] second
Content-Transfer-Encoding: base64
LS0tCiBmaWxlIHwgIEJpbiAxMzU3IC0+IDEzNTcgYnl0ZXMKIDEgZmlsZXMgY2hhbmdlZCwg
MCBpbnNlcnRpb25zKCspLCAwIGRlbGV0aW9ucygtKQoKZGlmZiAtLWdpdCBhL2ZpbGUgYi9m
aWxlCmluZGV4IDc3MzYxZDguLjllMDJiZTYgMTAwNjQ0Ci0tLSBhL2ZpbGUKKysrIGIvZmls
ZQpAQCAtMSwxMiArMSwxMiBAQAogTG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNl
Y3RldHVlciBhZGlwaXNjaW5nIGVsaXQuIFN1c3BlbmRpc3NlCiBzaXQgYW1ldCB0dXJwaXMg
ZWdldCBlc3QgY3Vyc3VzIGxhb3JlZXQuIEFsaXF1YW0gbWF1cmlzLiBQcmFlc2VudAotdm9s
dXRwYXQuIFByb2luIGluIHB1cnVzLiBOdWxsYSB1cm5hIHNhcGllbiwgZGFwaWJ1cyBzaXQg
YW1ldCwKK3ZvbHV0cGF0LiBQcm9pbiBpbiBwdXJ1cy4gTnVsbGEgdXJuYSBzYXBpZW4sIGRh
cGkAdXMgc2l0IGFtZXQsCiBoZW5kcmVyaXQgbmVjLCB0ZW1wdXMgZXUsIG1pLiBVdCBwb3J0
YSwgbGVvIGlkIHRpbmNpZHVudCB1bGxhbWNvcnBlciwKLXZlbGl0IGZlbGlzIHRyaXN0aXF1
ZSBhbnRlLCBhdCBsb2JvcnRpcyBkaWFtIHBlZGUgdXQgZHVpLiBQcm9pbiBhYwordmVsaXQg
ZmVsaXMgdHJpc3RpcXVlIGFudGUsIGF0IGxvAG9ydGlzIGRpYW0gcGVkZSB1dCBkdWkuIFBy
b2luIGFjCiBsZWN0dXMuIERvbmVjIGF0IG1hc3NhIGFjIGlwc3VtIGhlbmRyZXJpdCBzb2xs
aWNpdHVkaW4uIE5hbSBkaWN0dW0KIG5pc2kgc2VkIG1pLiBEdWlzIHNlZCBhbnRlLiBVdCB2
aXRhZSBlc3QgdXQgZHVpIHVsdHJpY2llcyBkaWduaXNzaW0uCiAKLUluIHZlbCBvZGlvIGVn
ZXQgbmlzbCBjb252YWxsaXMgdm9sdXRwYXQuIE1vcmJpIHZpdGFlIG5pYmguIE51bGxhbQor
SW4gdmVsIG9kaW8gZWdldCBuaXNsIGNvbnZhbGxpcyB2b2x1dHBhdC4gTW9yAGkgdml0YWUg
bmkAaC4gTnVsbGFtCiBhY2N1bXNhbiwgZG9sb3IgcXVpcyBhbGlxdWFtIHNjZWxlcmlzcXVl
LCBlbGl0IGVuaW0gY29uZGltZW50dW0KIG1hdXJpcywgbm9uIHRyaXN0aXF1ZSBtYXVyaXMg
dHVycGlzIGV0IG1hdXJpcy4gVXQgbm9uIG5pc2wuIE5hbSBkaWFtCiBtaSwgc2VtcGVyIHBv
c3VlcmUsIGVsZWlmZW5kIHV0LCBhdWN0b3IgdmVsLCBlcmF0LiBTZWQgcG9zdWVyZQpAQCAt
MTYsNyArMTYsNyBAQCBzZWQgZXN0LiBFdGlhbSBkaWFtIGZlbGlzLCBmZXJtZW50dW0gZWdl
dCwgYWRpcGlzY2luZyBhdCwgcG9zdWVyZSBpbiwKIGR1aS4gRXRpYW0gbHVjdHVzLgogCiBO
dWxsYSBpZCBhdWd1ZS4gTmFtIGlhY3VsaXMgYWNjdW1zYW4gbmlzaS4gU3VzcGVuZGlzc2Ug
cG90ZW50aS4gTnVuYwotdmFyaXVzIGF1Z3VlIG5lYyBvcmNpLiBVdCBjb25kaW1lbnR1bSBk
b2xvciBzYWdpdHRpcyBuaWJoLiBTdXNwZW5kaXNzZQordmFyaXVzIGF1Z3VlIG5lYyBvcmNp
LiBVdCBjb25kaW1lbnR1bSBkb2xvciBzYWdpdHRpcyBuaQBoLiBTdXNwZW5kaXNzZQogdGVt
cG9yIGxlY3R1cyBzZWQgbWFnbmEuIFN1c3BlbmRpc3NlIHBvdGVudGkuIE51bGxhbSB0ZW1w
b3IgaXBzdW0uIFNlZAogbW9sZXN0aWUgdGVsbHVzLiBQaGFzZWxsdXMgbGlndWxhLiBJbiB2
ZWhpY3VsYSB1bHRyaWNlcwogbmlzaS4gU3VzcGVuZGlzc2UgZmVsaXMgYXVndWUsIHBlbGxl
bnRlc3F1ZSBhdCwgZGljdHVtIHZpdmVycmEsCi0tIAoxLjUuNS4xLjU0MC5nNTc3ODAKCg==
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册