hypermail patches Paul DuBois dubois@primate.wisc.edu http://www.primate.wisc.edu/people/dubois 24 May 1996 This file contains patches to correct certain problems with hypermail 1.02. The following problems were found by me: parse.c: - Off-by-one errors in string-collection loops can cause buffer overwrites - Mailbox files that begin with blank lines can send hypermail into an infinite loop string.c: - Incorrect hyperlink written for in-reply-to's (was generating 3-digit link references, whereas files are written with 4-digit names) In addition, for parse.c: /* The getid subroutine in the next line was modified by Patrick Goebel (02/14/1996) to avoid a segmentation fault when messages have non-standard message ids. Some mailers are sending out message ids that aren't enclosed in <...> or begin on the next line. The modifications were modelled on the getsubject routine that follows. */ To apply these patches, you should be in the hypermail source directory. Just feed this file into patch: % patch < hm-patches *** hypermail.h.orig Sun Jul 31 20:01:50 1994 --- hypermail.h Fri May 24 15:06:55 1996 *************** *** 19,24 **** --- 19,25 ---- #define NONAME "(no name)" #define NODATE "(no date)" #define NOEMAIL "(no email)" + #define NOMSGID "(no message-id)" #define NOSUBJECT "(no subject)" #define MAXLINE 1000 #define MAXFILELEN 100 *************** *** 26,32 **** #define NUMSTRLEN 10 #define MAILSTRLEN 80 #define DATESTRLEN 80 ! #define MSGDSTRLEN 80 #define REPYSTRLEN 240 #define SUBJSTRLEN 100 #define URLSTRLEN 100 --- 27,33 ---- #define NUMSTRLEN 10 #define MAILSTRLEN 80 #define DATESTRLEN 80 ! #define MSGDSTRLEN 80 /* must be <= REPLYSTRLEN */ #define REPYSTRLEN 240 #define SUBJSTRLEN 100 #define URLSTRLEN 100 *** parse.c.orig Sun Jul 31 20:35:51 1994 --- parse.c Fri May 24 15:03:49 1996 *************** *** 25,31 **** --- 25,33 ---- line[MAXLINE], tmpfrom[MAXLINE], fromdate[DATESTRLEN], oldline[MAXLINE]; int num, isinheader, hassubject, hasdate, wasinreply; + int skipblanks; struct body *bp; + char *c; if (!strcmp(mbox, "NONE") || use_stdin) fp = stdin; *************** *** 45,50 **** --- 47,53 ---- hasdate = 0; wasinreply = 0; isinheader = 1; + skipblanks = 1; /* true only at top of file */ inreply[0] = '\0'; tmpfrom[0] = '\0'; oldline[0] = '\0'; *************** *** 64,69 **** --- 67,77 ---- printf("Loading mailbox \"%s\"... ", mbox); } while (fgets(line, MAXLINE, fp) != NULL) { + if (skipblanks) { /* skip blank lines at top of file */ + if (*line == '\n') + continue; + skipblanks = 0; + } if (isinheader) { if (!strncmp(line, "Received:", 9) || !strncmp(line, "Return-Path:", 12) || *************** *** 84,89 **** --- 92,103 ---- } else if (!strncmp(line, "Message-Id:", 11)) { bp = (struct body *) addbody(bp, line); + + /* The getid subroutine in the next line was patched + to avoid a segmentation fault from strchr when messages + have non-standard message ids. + */ + strcpy(msgid, (char *) getid(line)); } else if (!strncmp(line, "Subject:", 8)) { *************** *** 516,522 **** c += 2; while (isspace(*c)) c++; ! for (i = 0; *c && *c != '\n' && i < DATESTRLEN; c++) date[i++] = *c; date[i] = '\0'; --- 530,536 ---- c += 2; while (isspace(*c)) c++; ! for (i = 0; *c && *c != '\n' && i < DATESTRLEN - 1; c++) date[i++] = *c; date[i] = '\0'; *************** *** 539,545 **** if (days[i] == NULL) tmpdate[0] = '\0'; else { ! for (i = 0; *c && *c != '\n' && i < DATESTRLEN; c++) tmpdate[i++] = *c; tmpdate[i] = '\0'; if (tmpdate[16] != ':') { --- 553,559 ---- if (days[i] == NULL) tmpdate[0] = '\0'; else { ! for (i = 0; *c && *c != '\n' && i < DATESTRLEN - 1; c++) tmpdate[i++] = *c; tmpdate[i] = '\0'; if (tmpdate[16] != ':') { *************** *** 578,584 **** while (isspace(*c)) c++; for (i = 0; *c && *c != '(' && *c != ' ' && ! *c != '\n' && i < MAILSTRLEN; c++) email[i++] = *c; email[i] = '\0'; } --- 592,598 ---- while (isspace(*c)) c++; for (i = 0; *c && *c != '(' && *c != ' ' && ! *c != '\n' && i < MAILSTRLEN - 1; c++) email[i++] = *c; email[i] = '\0'; } *************** *** 590,596 **** c--; c++; for (i = 0; *c && *c != '>' && *c != ' ' && *c != '\n' && ! i < MAILSTRLEN; c++) email[i++] = *c; email[i] = '\0'; --- 604,610 ---- c--; c++; for (i = 0; *c && *c != '>' && *c != ' ' && *c != '\n' && ! i < MAILSTRLEN - 1; c++) email[i++] = *c; email[i] = '\0'; *************** *** 612,618 **** } for (i = 0; *c && *c != '<' && *c != '\"' && *c != ')' && ! *c != '(' && *c != '\n' && i < NAMESTRLEN; c++) name[i++] = *c; if (*c == '<' || *c == '(') name[--i] = '\0'; --- 626,632 ---- } for (i = 0; *c && *c != '<' && *c != '\"' && *c != ')' && ! *c != '(' && *c != '\n' && i < NAMESTRLEN - 1; c++) name[i++] = *c; if (*c == '<' || *c == '(') name[--i] = '\0'; *************** *** 623,628 **** --- 637,650 ---- /* Grabs the message ID, like <...> from the Message-ID: header. */ + /* The getid subroutine in the next line was modified by Patrick Goebel + (02/14/1996) to avoid a segmentation fault when messages have + non-standard message ids. Some mailers are sending out message + ids that aren't enclosed in <...> or begin on the next line. + The modifications were modelled on the getsubject routine that + follows. + */ + char *getid(line) char *line; { *************** *** 630,643 **** char *c; static char msgid[MSGDSTRLEN]; ! c = (char *) strchr(line, '<') + 1; ! for (i = 0; *c && *c != '>' && *c != '\n' && i < MSGDSTRLEN; c++) { ! if (*c == '\\') continue; msgid[i++] = *c; } msgid[i] = '\0'; return msgid; } --- 652,673 ---- char *c; static char msgid[MSGDSTRLEN]; ! c = (char *) strchr(line, ':') + 2; ! while (isspace(*c)) ! c++; ! ! for (i = 0; *c && *c != '\n' && i < MSGDSTRLEN - 1; c++) { ! if (*c == '\\' || *c == '<' || *c == '>') continue; msgid[i++] = *c; } msgid[i] = '\0'; + for (i--; i >= 0 && isspace(msgid[i]); i--) + msgid[i] = '\0'; + if (msgid[0] == NULL || isspace(msgid[0]) || msgid[0] == '\n') + strcpy(msgid, NOMSGID); + return msgid; } *************** *** 654,660 **** c = (char *) strchr(line, ':') + 2; while (isspace(*c)) c++; ! for (i = 0; *c && *c != '\n' && i < SUBJSTRLEN; c++) subject[i++] = *c; subject[i] = '\0'; for (i--; i >= 0 && isspace(subject[i]); i--) --- 684,690 ---- c = (char *) strchr(line, ':') + 2; while (isspace(*c)) c++; ! for (i = 0; *c && *c != '\n' && i < SUBJSTRLEN - 1; c++) subject[i++] = *c; subject[i] = '\0'; for (i--; i >= 0 && isspace(subject[i]); i--) *************** *** 680,686 **** if ((c = (char *) strstr(line, "dated: ")) != NULL) { c += 7; ! for (i = 0; *c && *c != '.' && *c != '\n' && i < REPYSTRLEN; c++) reply[i++] = *c; reply[i] = '\0'; --- 710,716 ---- if ((c = (char *) strstr(line, "dated: ")) != NULL) { c += 7; ! for (i = 0; *c && *c != '.' && *c != '\n' && i < REPYSTRLEN - 1; c++) reply[i++] = *c; reply[i] = '\0'; *************** *** 689,695 **** if ((c = (char *) strchr(line, '<')) != NULL ) { c++; ! for (i = 0; *c && *c != '>' && *c != '\n' && i < MSGDSTRLEN; c++) { if (*c == '\\') continue; --- 719,725 ---- if ((c = (char *) strchr(line, '<')) != NULL ) { c++; ! for (i = 0; *c && *c != '>' && *c != '\n' && i < MSGDSTRLEN - 1; c++) { if (*c == '\\') continue; *************** *** 704,710 **** if (*c == '\"') c++; for (i = 0; *c && *c != '.' && *c != '\n' && *c != 'f' && ! i < REPYSTRLEN; c++) reply[i++] = *c; reply[i] = '\0'; if (*c == 'f') --- 734,740 ---- if (*c == '\"') c++; for (i = 0; *c && *c != '.' && *c != '\n' && *c != 'f' && ! i < REPYSTRLEN - 1; c++) reply[i++] = *c; reply[i] = '\0'; if (*c == 'f') *************** *** 715,717 **** --- 745,748 ---- reply[0] = '\0'; return reply; } + *** string.c.orig Mon Aug 1 01:04:55 1994 --- string.c Fri May 17 10:32:53 1996 *************** *** 96,102 **** i++; } tmpline3[j] = '\0'; ! sprintf(tmpline3, "%s", tmpline3, status); for (j = strlen(tmpline3); tmpline4[i] && tmpline4[i] != '\n' && j < MAXLINE; i++) --- 96,102 ---- i++; } tmpline3[j] = '\0'; ! sprintf(tmpline3, "%s", tmpline3, status); for (j = strlen(tmpline3); tmpline4[i] && tmpline4[i] != '\n' && j < MAXLINE; i++)