]> diplodocus.org Git - nmh/blobdiff - sbr/m_getfld.c
ap: Fix write past end of addrs[] array.
[nmh] / sbr / m_getfld.c
index a7622b563f3d43e076d9c522a30c527326c9d42b..5c5b4a3a88274646175e993af895e64593bd5282 100644 (file)
    names are typically short (~8 char) and the loop that extracts them
    might terminate on a colon, newline or max width.  I considered
    using a Vax "scanc" to locate the end of the field followed by a
-   "bcopy" but the routine call overhead on a Vax is too large for this
+   "memmove" but the routine call overhead on a Vax is too large for this
    to work on short names.  If Berkeley ever makes "inline" part of the
    C optimiser (so things like "scanc" turn into inline instructions) a
    change here would be worthwhile.
    so message bodies average at least a few hundred characters.
    Assuming your system uses reasonably sized stdio buffers (1K or
    more), this routine should be able to remove the body in large
-   (>500 byte) chunks.  The makes the cost of a call to "bcopy"
+   (>500 byte) chunks.  The makes the cost of a call to "memmove"
    small but there is a premium on checking for the eom in packed
    maildrops.  The eom pattern is always a simple string so we can
    construct an efficient pattern matcher for it (e.g., a Vax "matchc"
@@ -268,7 +268,8 @@ void
 m_getfld_state_init (m_getfld_state_t *gstate, FILE *iob) {
     m_getfld_state_t s;
 
-    s = *gstate = (m_getfld_state_t) mh_xmalloc(sizeof (struct m_getfld_state));
+    NEW(s);
+    *gstate = s;
     s->readpos = s->end = s->msg_buf;
     s->bytes_read = s->total_bytes_read = 0;
     s->last_caller_pos = s->last_internal_pos = 0;
@@ -450,31 +451,29 @@ read_more (m_getfld_state_t s) {
    but EOF is typically 0xffffffff. */
 static int
 Getc (m_getfld_state_t s) {
-    if (s->end - s->readpos < 1  &&  read_more (s) == 0) {
+    if ((s->end - s->readpos < 1 && read_more (s) == 0) ||
+        s->readpos >= s->end)
         return EOF;
-    } else {
-        ++s->bytes_read;
-        return s->readpos < s->end  ?  (unsigned char) *s->readpos++  :  EOF;
-    }
+
+    s->bytes_read++;
+    return (unsigned char)*s->readpos++;
 }
 
 static int
 Peek (m_getfld_state_t s) {
     if (s->end - s->readpos < 1  &&  read_more (s) == 0) {
         return EOF;
-    } else {
-        return s->readpos < s->end  ?  (unsigned char) *s->readpos  :  EOF;
     }
+    return s->readpos < s->end  ?  (unsigned char) *s->readpos  :  EOF;
 }
 
 static int
 Ungetc (int c, m_getfld_state_t s) {
     if (s->readpos == s->msg_buf) {
        return EOF;
-    } else {
-       --s->bytes_read;
-       return *--s->readpos = (unsigned char) c;
     }
+    --s->bytes_read;
+    return *--s->readpos = (unsigned char) c;
 }
 
 
@@ -483,23 +482,23 @@ m_getfld (m_getfld_state_t *gstate, char name[NAMESZ], char *buf, int *bufsz,
           FILE *iob)
 {
     m_getfld_state_t s;
-    register char *cp;
-    register int max, n, c;
+    char *cp;
+    int max, n, c;
 
     enter_getfld (gstate, iob);
     s = *gstate;
 
-    if ((c = Getc(s)) < 0) {
+    if ((c = Getc(s)) == EOF) {
        *bufsz = *buf = 0;
        leave_getfld (s);
        return s->state = FILEEOF;
     }
     if (eom (c, s)) {
        /* flush null messages */
-       while ((c = Getc(s)) >= 0 && eom (c, s))
+       while ((c = Getc(s)) != EOF && eom (c, s))
            ;
 
-       if (c >= 0)
+       if (c != EOF)
            Ungetc(c, s);
        *bufsz = *buf = 0;
        leave_getfld (s);
@@ -510,13 +509,14 @@ m_getfld (m_getfld_state_t *gstate, char name[NAMESZ], char *buf, int *bufsz,
        case FLD:
            if (c == '\n' || c == '-') {
                /* we hit the header/body separator */
-               while (c != '\n' && (c = Getc(s)) >= 0) continue;
+               while (c != '\n' && (c = Getc(s)) != EOF)
+                    ;
 
-               if (c < 0 || (c = Getc(s)) < 0 || eom (c, s)) {
+               if (c == EOF || (c = Getc(s)) == EOF || eom (c, s)) {
                    /* flush null messages */
-                   while ((c = Getc(s)) >= 0 && eom (c, s))
+                   while ((c = Getc(s)) != EOF && eom (c, s))
                        ;
-                   if (c >= 0)
+                   if (c != EOF)
                        Ungetc(c, s);
                    *bufsz = *buf = 0;
                    leave_getfld (s);
@@ -581,13 +581,17 @@ m_getfld (m_getfld_state_t *gstate, char name[NAMESZ], char *buf, int *bufsz,
                memcpy (buf, name, n - 1);
                buf[n - 1] = '\n';
                buf[n] = '\0';
+                /* Indicate this wasn't a header field using a character
+                   that can't appear in a header field. */
+                name[0] = ':';
                /* The last character read was '\n'.  s->bytes_read
                   (and n) include that, but it was not put into the
                   name array in the for loop above.  So subtract 1. */
                *bufsz = --s->bytes_read;  /* == n - 1 */
                leave_getfld (s);
                return s->state = BODY;
-           } else if (max <= n) {
+           }
+            if (max <= n) {
                /* By design, the loop above discards the last character
                    it had read.  It's in c, use it. */
                *cp++ = c;
@@ -657,6 +661,7 @@ m_getfld (m_getfld_state_t *gstate, char name[NAMESZ], char *buf, int *bufsz,
             */
            char *bp;
 
+            name[0] = '\0';
            max = *bufsz-1;
            /* Back up and store the current position. */
            bp = --s->readpos;
@@ -760,11 +765,11 @@ void
 m_unknown(m_getfld_state_t *gstate, FILE *iob)
 {
     m_getfld_state_t s;
-    register int c;
+    int c;
     char text[MAX_DELIMITER_SIZE];
     char from[] = "From ";
-    register char *cp;
-    register char *delimstr;
+    char *cp;
+    char *delimstr;
     unsigned int i;
 
     enter_getfld (gstate, iob);
@@ -797,7 +802,8 @@ m_unknown(m_getfld_state_t *gstate, FILE *iob)
     if (i == sizeof from-1  &&  strncmp (text, "From ", sizeof from-1) == 0) {
        s->msg_style = MS_MBOX;
        delimstr = "\nFrom ";
-       while ((c = Getc (s)) != '\n' && c >= 0) continue;
+       while ((c = Getc(s)) != EOF && c != '\n')
+            ;
     } else {
        /* not a Unix style maildrop */
        s->readpos -= s->bytes_read;
@@ -830,9 +836,9 @@ m_unknown(m_getfld_state_t *gstate, FILE *iob)
 
     if (s->msg_style == MS_MMDF) {
        /* flush extra msg hdrs */
-       while ((c = Getc(s)) >= 0 && eom (c, s))
+       while ((c = Getc(s)) != EOF && eom (c, s))
            ;
-       if (c >= 0)
+       if (c != EOF)
            Ungetc(c, s);
     }
 
@@ -847,7 +853,7 @@ m_unknown(m_getfld_state_t *gstate, FILE *iob)
 static int
 m_Eom (m_getfld_state_t s)
 {
-    register int i;
+    int i;
     char text[MAX_DELIMITER_SIZE];
     char *cp;
 
@@ -880,9 +886,8 @@ m_Eom (m_getfld_state_t s)
 
     if (s->msg_style == MS_MBOX) {
        int c;
-       while ((c = Getc (s)) != '\n')
-           if (c < 0)
-               break;
+       while ((c = Getc(s)) != EOF && c != '\n')
+            ;
     }
 
     return 1;
@@ -892,11 +897,11 @@ m_Eom (m_getfld_state_t s)
 static char *
 matchc(int patln, char *pat, int strln, char *str)
 {
-       register char *es = str + strln - patln;
-       register char *sp;
-       register char *pp;
-       register char *ep = pat + patln;
-       register char pc = *pat++;
+       char *es = str + strln - patln;
+       char *sp;
+       char *pp;
+       char *ep = pat + patln;
+       char pc = *pat++;
 
        for(;;) {
                while (pc != *str++)