From cfb444d37fc236a9fdac369cbcf2a5bfc37a33f5 Mon Sep 17 00:00:00 2001 From: Ralph Corderoy Date: Fri, 26 May 2017 23:34:10 +0100 Subject: [PATCH 1/1] uip/mhparse.c: Fix body starting a byte too soon when no blank line. m_getfld() returns BODY when the headers run into a line without a colon instead of being separated from the body by a blank line. The file's position and the returned `bufsz' differ from the normal case of a blank line and then the start of the body, causing confusion. get_content() was aware of the difference, documented it, and attempted to correct for it, but got it wrong and included the `\n' that terminates the last real header at the start of the "body". This affected a struct Content's c_begin. Use the correct file position for c_begin, adding a comment that explains the theory for both cases. Add a test-mhlist case that checks mhlist(1) states the body size is the same whether it is separated from the headers by a blank line or not. Correct existing test/bad-input/test-header test that expected the extra blank line to be counted and to appear in the output. --- test/bad-input/test-header | 3 +-- test/mhlist/test-mhlist | 17 +++++++++++++++++ uip/mhparse.c | 23 ++++++++++++++++++----- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/test/bad-input/test-header b/test/bad-input/test-header index 0148db57..a8ab49e3 100755 --- a/test/bad-input/test-header +++ b/test/bad-input/test-header @@ -69,8 +69,7 @@ From: foo@example.edu Subject: test -[ part - text/plain - 70B ] - +[ part - text/plain - 69B ] This is a multi-part message in MIME format. I am a stupid spammer. diff --git a/test/mhlist/test-mhlist b/test/mhlist/test-mhlist index fedc0144..366733e4 100755 --- a/test/mhlist/test-mhlist +++ b/test/mhlist/test-mhlist @@ -61,6 +61,23 @@ EOF run_prog mhlist -file - < "$MH_TEST_DIR/Mail/inbox/5" > $actual 2>&1 check $expected $actual +# Check message with no blank line separating the headers from the body. +# Shouldn't make a difference to the size of the body part. +# Bug meant no-blank-line case was one bigger by including the `\n' +# ending the last header. +f=$MH_TEST_DIR/$$.blank +cat >$f-yes <<\E +foo: bar + +body1 +body2 +E +sed '/^$/d' $f-yes >$f-no +run_prog mhlist -file $f-yes >$actual-yes +run_prog mhlist -file $f-no >$actual-no +check $actual-yes $actual-no +rm $f-yes $f-no + # check message number greater than highest run_test 'mhlist 11' "mhlist: message 11 doesn't exist" diff --git a/uip/mhparse.c b/uip/mhparse.c index 69660a91..1a7fe520 100644 --- a/uip/mhparse.c +++ b/uip/mhparse.c @@ -334,12 +334,25 @@ get_content (FILE *in, char *file, int toplevel) continue; case BODY: + /* There are two cases. The unusual one is when there is no + * blank line between the headers and the body. This is + * indicated by the name of the header starting with `:'. + * + * For both cases, normal first, `1' is the desired c_begin + * file position for the start of the body, and `2' is the + * file position when buf is returned. + * + * f o o : b a r \n \n b o d y \n bufsz = 6 + * 1 2 move -5 + * f o o : b a r \n b o d y \n bufsz = 4 + * 1 2 move -4 + * + * For the normal case, bufsz includes the + * header-terminating `\n', even though it is not in buf, + * but bufsz isn't affected when it's missing in the unusual + * case. */ if (name[0] == ':') { - /* Special case: no blank line between header and body. The - file position indicator is on the newline at the end of the - line, but it needs to be one prior to the beginning of the - line. So subtract the length of the line, bufsz, plus 1. */ - ct->c_begin = ftell (in) - (bufsz + 1); + ct->c_begin = ftell(in) - bufsz; } else { ct->c_begin = ftell (in) - (bufsz - 1); } -- 2.48.1