From a139e1ddbbe5e7fe89d7eb4a5dc16d4b9698960a Mon Sep 17 00:00:00 2001 From: Eric Gillespie Date: Wed, 13 Aug 2008 01:01:12 +0000 Subject: [PATCH] * test/tests/mhshow/test-qp: Test various valid and invalid escape sequences. * uip/mhparse.c (openQuoted): Simplify the decode-or-show for loop by peeking ahead to the next byte(s) when encountering '=', and just let invalid escape sequences through as literals (fixes bug #15245). --- ChangeLog | 9 ++++ test/tests/mhshow/test-qp | 58 ++++++++++++++++++++++++ uip/mhparse.c | 108 ++++++++++++++++++++------------------------- 3 files changed, 114 insertions(+), 61 deletions(-) create mode 100644 test/tests/mhshow/test-qp diff --git a/ChangeLog b/ChangeLog index 1016132..e33aec2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2008-08-12 Eric Gillespie + + * test/tests/mhshow/test-qp: Test various valid and invalid + escape sequences. + + * uip/mhparse.c (openQuoted): Simplify the decode-or-show for loop by + peeking ahead to the next byte(s) when encountering '=', and just let + invalid escape sequences through as literals (fixes bug #15245). + 2008-08-12 Peter Maydell * autogen.sh (new file): add script for running the GNU diff --git a/test/tests/mhshow/test-qp b/test/tests/mhshow/test-qp new file mode 100644 index 0000000..25dde49 --- /dev/null +++ b/test/tests/mhshow/test-qp @@ -0,0 +1,58 @@ +#!/bin/sh + +set -e + +expected=$MH_TEST_DIR/$$.expected +actual=$MH_TEST_DIR/$$.actual + +# Write message with bogus quoted-printable data. +msgfile=$(mhpath new) +msgnum=$(basename $msgfile) +cat > $msgfile < $expected < $actual 2>&1 +diff -u $expected $actual diff --git a/uip/mhparse.c b/uip/mhparse.c index 4887d9a..6771789 100644 --- a/uip/mhparse.c +++ b/uip/mhparse.c @@ -1859,8 +1859,6 @@ openQuoted (CT ct, char **file) fseek (ct->c_fp, ct->c_begin, SEEK_SET); while (len > 0) { - char *dp; - if (fgets (buffer, sizeof(buffer) - 1, ct->c_fp) == NULL) { content_error (NULL, ct, "premature eof"); goto clean_up; @@ -1876,79 +1874,67 @@ openQuoted (CT ct, char **file) *++ep = '\n', ep++; for (; cp < ep; cp++) { - if (quoted) { - if (quoted > 1) { - if (!isxdigit (*cp)) { -invalid_hex: - dp = "expecting hexidecimal-digit"; - goto invalid_encoding; - } + if (quoted > 0) { + /* in an escape sequence */ + if (quoted == 1) { + /* at byte 1 of an escape sequence */ + mask = hex2nib[*cp & 0x7f]; + /* next is byte 2 */ + quoted = 2; + } else { + /* at byte 2 of an escape sequence */ mask <<= 4; mask |= hex2nib[*cp & 0x7f]; putc (mask, ce->ce_fp); if (digested) MD5Update (&mdContext, &mask, 1); - } else { - switch (*cp) { - case ':': - putc (*cp, ce->ce_fp); - if (digested) - MD5Update (&mdContext, (unsigned char *) ":", 1); - break; - - default: - if (!isxdigit (*cp)) - goto invalid_hex; - mask = hex2nib[*cp & 0x7f]; - quoted = 2; - continue; + if (ferror (ce->ce_fp)) { + content_error (ce->ce_file, ct, "error writing to"); + goto clean_up; } + /* finished escape sequence; next may be literal or a new + * escape sequence */ + quoted = 0; } - - if (ferror (ce->ce_fp)) { - content_error (ce->ce_file, ct, "error writing to"); - goto clean_up; - } - quoted = 0; + /* on to next byte */ continue; } - switch (*cp) { - default: - if (*cp < '!' || *cp > '~') { - int i; - dp = "expecting character in range [!..~]"; - -invalid_encoding: - i = strlen (invo_name) + 2; - content_error (NULL, ct, - "invalid QUOTED-PRINTABLE encoding -- %s,\n%*.*sbut got char 0x%x", - dp, i, i, "", *cp); - goto clean_up; - } - /* and fall...*/ - case ' ': - case '\t': - case '\n': - putc (*cp, ce->ce_fp); - if (digested) { - if (*cp == '\n') - MD5Update (&mdContext, (unsigned char *) "\r\n",2); - else - MD5Update (&mdContext, (unsigned char *) cp, 1); + /* not in an escape sequence */ + if (*cp == '=') { + /* starting an escape sequence, or invalid '='? */ + if (cp + 1 < ep && cp[1] == '\n') { + /* "=\n" soft line break, eat the \n */ + cp++; + continue; } - if (ferror (ce->ce_fp)) { - content_error (ce->ce_file, ct, "error writing to"); - goto clean_up; + if (cp + 1 >= ep || cp + 2 >= ep) { + /* We don't have 2 bytes left, so this is an invalid + * escape sequence; just show the raw bytes (below). */ + } else if (isxdigit (cp[1]) && isxdigit (cp[2])) { + /* Next 2 bytes are hex digits, making this a valid escape + * sequence; let's decode it (above). */ + quoted = 1; + continue; + } else { + /* One or both of the next 2 is out of range, making this + * an invalid escape sequence; just show the raw bytes + * (below). */ } - break; + } - case '=': - if (*++cp != '\n') { - quoted = 1; - cp--; + /* Just show the raw byte. */ + putc (*cp, ce->ce_fp); + if (digested) { + if (*cp == '\n') { + MD5Update (&mdContext, (unsigned char *) "\r\n",2); + } else { + MD5Update (&mdContext, (unsigned char *) cp, 1); } - break; + } + if (ferror (ce->ce_fp)) { + content_error (ce->ce_file, ct, "error writing to"); + goto clean_up; } } } -- 1.7.10.4