summaryrefslogtreecommitdiff
path: root/builtin-mailsplit.c
diff options
context:
space:
mode:
authorJohannes Schindelin <Johannes.Schindelin@gmx.de>2008-05-16 14:03:30 +0100
committerJunio C Hamano <gitster@pobox.com>2008-05-25 13:21:40 -0700
commitcce8d6fdb4d7170a73763586daf6ac4f6b8fce2c (patch)
tree636ecb4162561aa5bdfa5a86128fa941fc1ea617 /builtin-mailsplit.c
parent182fb4df9120257c2e6b041dd58eef3de5b530d2 (diff)
downloadgit-cce8d6fdb4d7170a73763586daf6ac4f6b8fce2c.tar.gz
mailsplit and mailinfo: gracefully handle NUL characters
The function fgets() has a big problem with NUL characters: it reads them, but nobody will know if the NUL comes from the file stream, or was appended at the end of the line. So implement a custom read_line_with_nul() function. Noticed by Tommy Thorn. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin-mailsplit.c')
-rw-r--r--builtin-mailsplit.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/builtin-mailsplit.c b/builtin-mailsplit.c
index 46b27cdaea..e4d977bafb 100644
--- a/builtin-mailsplit.c
+++ b/builtin-mailsplit.c
@@ -45,6 +45,25 @@ static int is_from_line(const char *line, int len)
/* Could be as small as 64, enough to hold a Unix "From " line. */
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);
+ buf[len++] = c;
+ if (c == EOF || c == '\n' || len + 1 >= size)
+ break;
+ }
+
+ if (c == EOF)
+ len--;
+ buf[len] = '\0';
+
+ return len;
+}
+
/* Called with the first line (potentially partial)
* already in buf[] -- normally that should begin with
* the Unix "From " line. Write it into the specified
@@ -70,19 +89,19 @@ static int split_one(FILE *mbox, const char *name, int allow_bare)
* "From " and having something that looks like a date format.
*/
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");
- if (fgets(buf, sizeof(buf), mbox) == NULL) {
+ len = read_line_with_nul(buf, sizeof(buf), mbox);
+ if (len == 0) {
if (feof(mbox)) {
status = 1;
break;
}
die("cannot read mbox");
}
- len = strlen(buf);
if (!is_partial && !is_bare && is_from_line(buf, len))
break; /* done with one message */
}