/*
* m_getfld.c -- read/parse a message
*
- * $Id$
- *
* This code is Copyright (c) 2002, by the authors of nmh. See the
* COPYRIGHT file in the root directory of the nmh distribution for
* complete copyright information.
* . hit the end of the buffer. (loop)
*/
if (c == '\n') {
- *cp = *buf = 0;
- advise (NULL, "eol encountered in field \"%s\"", name);
- state = FMTERR;
- goto finish;
+ /* We hit the end of the line without seeing ':' to
+ * terminate the field name. This is usually (always?)
+ * spam. But, blowing up is lame, especially when
+ * scan(1)ing a folder with such messages. Pretend such
+ * lines are the first of the body (at least mutt also
+ * handles it this way). */
+
+ /* See if buf can hold this line, since we were assuming
+ * we had a buffer of NAMESZ, not bufsz. */
+ /* + 1 for the newline */
+ if (bufsz < j + 1) {
+ /* No, it can't. Oh well, guess we'll blow up. */
+ *cp = *buf = 0;
+ advise (NULL, "eol encountered in field \"%s\"", name);
+ state = FMTERR;
+ goto finish;
+ }
+ memcpy (buf, name, j - 1);
+ buf[j - 1] = '\n';
+ buf[j] = '\0';
+ /* mhparse.c:get_content wants to find the position of the
+ * body start, but it thinks there's a blank line between
+ * the header and the body (naturally!), so seek back so
+ * that things line up even though we don't have that
+ * blank line in this case. Simpler parsers (e.g. mhl)
+ * get extra newlines, but that should be harmless enough,
+ * right? This is a corrupt message anyway. */
+ fseek (iob, ftell (iob) - 2, SEEK_SET);
+ return BODY;
}
if ((i -= j) <= 0) {
*cp = *buf = 0;
- advise (NULL, "field name \"%s\" exceeds %d bytes", name, NAMESZ - 1);
+ advise (NULL, "field name \"%s\" exceeds %d bytes", name, NAMESZ - 2);
state = LENERR;
goto finish;
}
ep = bp + c - 1;
if ((sp = pat_map[*ep])) {
do {
- cp = sp;
- while (*--ep == *--cp)
- ;
- if (cp < fdelim) {
- if (ep >= bp)
- /*
- * ep < bp means that all the buffer
- * contains is a prefix of delim.
- * If this prefix is really a delim, the
- * m_eom call at entry should have found
- * it. Thus it's not a delim and we can
- * take all of it.
+ /* This if() is true unless (a) the buffer is too
+ * small to contain this delimiter prefix, or
+ * (b) it contains exactly enough chars for the
+ * delimiter prefix.
+ * For case (a) obviously we aren't going to match.
+ * For case (b), if the buffer really contained exactly
+ * a delim prefix, then the m_eom call at entry
+ * should have found it. Thus it's not a delim
+ * and we know we won't get a match.
+ */
+ if (((sp - fdelim) + 2) <= c) {
+ cp = sp;
+ /* Unfortunately although fdelim has a preceding NUL
+ * we can't use this as a sentinel in case the buffer
+ * contains a NUL in exactly the wrong place (this
+ * would cause us to run off the front of fdelim).
+ */
+ while (*--ep == *--cp)
+ if (cp < fdelim)
+ break;
+ if (cp < fdelim) {
+ /* we matched the entire delim prefix,
+ * so only take the buffer up to there.
+ * we know ep >= bp -- check above prevents underrun
*/
c = (ep - bp) + 2;
- break;
- }
+ break;
+ }
+ }
/* try matching one less char of delim string */
ep = bp + c - 1;
} while (--sp > fdelim);