pag@hao.UUCP (Peter Gross) (03/29/84)
There is a problem with 2.10+ news' handling of unrecognized header fields that causes memory use to keep increasing. Certain notesfiles sites are adding special header fields for the notes system which are unregcognized by news. Other unrecognized fields are being generated by ARPA-gatewayed newsgroups. The dynamic memory allocated for this use is never released. On Vaxes and 32-bitters this just make the RSS get larger and larger. On PDP-11's, however, readnews and expire will run out of memory, failing in peculiar ways. I previously posted a fix to expire, but have discovered that problem appears in readnews too. So here are some revised fixes that supercede my previous one to alleviate the problem. The fixes are to header.c, expire.c, ifuncs.c, rfuncs.c, and rfuncs2.c. In the case of header.c and expire.c, I am including diffs from older pre-fix versions. --peter gross hao!pag *** old/header.c Thu Mar 29 10:44:00 1984 --- header.c Thu Mar 29 10:43:28 1984 *************** *** 9,14 * * 11/12/83 PAG Bug fix: missing site in path when prefix of current * site */ static char *SccsId = "@(#)header.c 3.4 3/29/84"; --- 9,21 ----- * * 11/12/83 PAG Bug fix: missing site in path when prefix of current * site + * + * 02/15/84 PAG Added check for failed malloc() + * + * 03/14/84 PAG Bug fix (typo) from USENET + * + * 03/26/84 PAG Bug fix: free() previously allocated memory in + * unrec[] array to prevent memory exhaustion */ static char *SccsId = "@(#)header.c 3.7 3/28/84"; *************** *** 11,17 * site */ ! static char *SccsId = "@(#)header.c 3.4 3/29/84"; #include <stdio.h> #include <sys/types.h> --- 18,24 ----- * unrec[] array to prevent memory exhaustion */ ! static char *SccsId = "@(#)header.c 3.7 3/28/84"; #include <stdio.h> #include <sys/types.h> *************** *** 37,42 int wholething; { register int len; if (wholething) bclear((char *) hp, sizeof (*hp)); --- 44,50 ----- int wholething; { register int len; + register short i; if (wholething) { *************** *** 39,44 register int len; if (wholething) bclear((char *) hp, sizeof (*hp)); seenrelay = 0; --- 47,66 ----- register short i; if (wholething) + { + /* + * Prevent memory exhaustion due to repeated malloc()'s + * of unrecognized header fields. Note that any local struct + * hbuf declarations used as args to hread() should zero out + * the unrec[] array, or mass confusion will result when this + * code is executed, and random stack values are given as + * arguments to free() + */ + for(i=0;i<NUNREC;i++) + if(hp->unrec[i] != (char *) NULL) + free(hp->unrec[i]); + else + break; bclear((char *) hp, sizeof (*hp)); } seenrelay = 0; *************** *** 40,46 if (wholething) bclear((char *) hp, sizeof (*hp)); ! seenrelay = 0; /* Check that it's a B news style header. */ --- 62,68 ----- else break; bclear((char *) hp, sizeof (*hp)); ! } seenrelay = 0; /* Check that it's a B news style header. */ *************** *** 130,138 int hdrlineno = 0; int iu; - for (iu=0; iu<NUNREC; iu++) - hp->unrec[iu] = NULL; - i = type(bfr); do { curpos = ftell(fp); --- 152,157 ----- int hdrlineno = 0; int iu; i = type(bfr); do { curpos = ftell(fp); *************** *** 213,218 case OTHER: if (unreccnt < NUNREC) { hp->unrec[unreccnt] = malloc(strlen(bfr) + 1); strcpy(hp->unrec[unreccnt], bfr); unreccnt++; } --- 232,239 ----- case OTHER: if (unreccnt < NUNREC) { hp->unrec[unreccnt] = malloc(strlen(bfr) + 1); + if(hp->unrec[unreccnt] == (char *) NULL) + xerror("frmread out of memory\n"); strcpy(hp->unrec[unreccnt], bfr); unreccnt++; } *************** *** 574,580 while ((c = getc(fp)) == ' ' || c == '\t') { /* for each cont line */ /* Continuation line. */ ! while ((c = getc(fp)) == ' ' || c == 't') /* skip white space */ ; if (tp-cp < len) {*tp++ = ' '; *tp++ = c;} while ((c = getc(fp)) != '\n' && c != EOF) --- 595,601 ----- while ((c = getc(fp)) == ' ' || c == '\t') { /* for each cont line */ /* Continuation line. */ ! while ((c = getc(fp)) == ' ' || c == '\t') /* skip white space */ ; if (tp-cp < len) {*tp++ = ' '; *tp++ = c;} while ((c = getc(fp)) != '\n' && c != EOF) *************** *** old/expire.c Thu Mar 29 09:27:28 1984 --- expire.c Wed Mar 28 09:42:25 1984 *************** *** 24,29 * 10/08/83 PAG Bug fix from USENET -- mkparents() has no return val * * 10/27/83 PAG Additions from Mark to remove junk articles */ static char *SccsId = "@(#)expire.c 3.7 3/29/84"; --- 24,35 ----- * 10/08/83 PAG Bug fix from USENET -- mkparents() has no return val * * 10/27/83 PAG Additions from Mark to remove junk articles + * + * 01/15/84 PAG Bug fix: repeated hread()'s can cause memory + * exhaustion + * + * 03/26/84 PAG Change to memory bug fix -- unrec fields now cleared + * in frmread() */ static char *SccsId = "@(#)expire.c 3.9 3/28/84"; *************** *** 26,32 * 10/27/83 PAG Additions from Mark to remove junk articles */ ! static char *SccsId = "@(#)expire.c 3.7 3/29/84"; #include "params.h" #include "ndir.h" --- 32,38 ----- * in frmread() */ ! static char *SccsId = "@(#)expire.c 3.9 3/28/84"; #include "params.h" #include "ndir.h" *************** *** 211,216 ohfd = xfopen(ARTFILE, "r"); nhfd = xfopen(NARTFILE, "w"); } while (TRUE) { if (nohistory) { --- 217,224 ----- ohfd = xfopen(ARTFILE, "r"); nhfd = xfopen(NARTFILE, "w"); } + for(i=0;i<NUNREC;i++) + h.unrec[i] = (char *) NULL; while (TRUE) { if (nohistory) { *************** *** 515,520 rhs.dptr = (char *) &number; rhs.dsize = sizeof(number); ! store(lhs, rhs); #endif } --- 523,529 ----- rhs.dptr = (char *) &number; rhs.dsize = sizeof(number); ! if(store(lhs, rhs) < 0) ! xerror("dbm cannot store %s",article); #endif } *************** *** old/ifuncs.c Thu Mar 29 09:19:19 1984 --- ifuncs.c Wed Mar 28 09:49:20 1984 *************** *** 1,5 /* * ifuncs - functions used by inews. */ static char *SccsId = "@(#)ifuncs.c 2.21 3/31/83"; --- 1,10 ----- /* * ifuncs - functions used by inews. + * + * R E V I S I O N H I S T O R Y + * + * 03/26/84 PAG Made local hbuf structs static so frmread() will + * not explode */ static char *SccsId = "@(#)ifuncs.c 2.22 3/28/84"; *************** *** 2,8 * ifuncs - functions used by inews. */ ! static char *SccsId = "@(#)ifuncs.c 2.21 3/31/83"; #include "iparams.h" --- 7,13 ----- * not explode */ ! static char *SccsId = "@(#)ifuncs.c 2.22 3/28/84"; #include "iparams.h" *************** *** 21,27 register FILE *fp; #ifndef u370 struct srec srec; ! struct hbuf h; #endif /* h is a local copy of the header we can scribble on */ --- 26,32 ----- register FILE *fp; #ifndef u370 struct srec srec; ! static struct hbuf h; #endif /* h is a local copy of the header we can scribble on */ *************** *** 78,84 register FILE *ofp; register int c; register char *ptr; ! struct hbuf hh; char TRANS[BUFLEN]; char *argv[20]; register int pid, fd; --- 83,89 ----- register FILE *ofp; register int c; register char *ptr; ! static struct hbuf hh; char TRANS[BUFLEN]; char *argv[20]; register int pid, fd; *************** *** old/rfuncs.c Thu Mar 29 09:13:15 1984 --- rfuncs.c Wed Mar 28 10:26:28 1984 *************** *** 7,12 * articles in the order of user's .newsrc * * 01/26/84 PAG Changed per-user copy of active to go in their /d? dir */ static char *SccsId = "@(#)rfuncs.c 3.3 3/29/84"; --- 7,15 ----- * articles in the order of user's .newsrc * * 01/26/84 PAG Changed per-user copy of active to go in their /d? dir + * + * 03/26/84 PAG Added code to zero out local hbuf unrec[] arrays + * so frmread() will not explode */ static char *SccsId = "@(#)rfuncs.c 3.4 3/28/84"; *************** *** 9,15 * 01/26/84 PAG Changed per-user copy of active to go in their /d? dir */ ! static char *SccsId = "@(#)rfuncs.c 3.3 3/29/84"; #include "rparams.h" --- 12,18 ----- * so frmread() will not explode */ ! static char *SccsId = "@(#)rfuncs.c 3.4 3/28/84"; #include "rparams.h" *************** *** 195,200 struct hbuf h; register char *ptr, *fname; int news = 0; ofp = xfopen(mktemp(outfile), "w"); if (aflag && *datebuf) --- 198,207 ----- struct hbuf h; register char *ptr, *fname; int news = 0; + int i; + + for(i=0;i<NUNREC;i++) + h.unrec[i] = (char *) NULL; ofp = xfopen(mktemp(outfile), "w"); if (aflag && *datebuf) *************** *** old/rfuncs2.c Thu Mar 29 09:17:02 1984 --- rfuncs2.c Wed Mar 28 09:52:31 1984 *************** *** 4,9 * R E V I S I O N H I S T O R Y * * 06/11/83 PAG Bug fix in printing out subdate */ static char *sccsid = "@(#)rfuncs2.c 3.1 3/29/84"; --- 4,12 ----- * R E V I S I O N H I S T O R Y * * 06/11/83 PAG Bug fix in printing out subdate + * + * 03/26/84 PAG Added code to zero out local hbuf unrec[] arrays + * so frmread() will not explode */ static char *sccsid = "@(#)rfuncs2.c 3.2 3/28/84"; *************** *** 5,11 * * 06/11/83 PAG Bug fix in printing out subdate */ ! static char *sccsid = "@(#)rfuncs2.c 3.1 3/29/84"; #include "rparams.h" --- 8,14 ----- * 03/26/84 PAG Added code to zero out local hbuf unrec[] arrays * so frmread() will not explode */ ! static char *sccsid = "@(#)rfuncs2.c 3.2 3/28/84"; #include "rparams.h" *************** *** 84,89 struct hbuf hh; int isprogram = 0; int isnew = 1; if ((hfp = fopen(file, "r")) == NULL) { printf("Can't get article.\n"); --- 87,93 ----- struct hbuf hh; int isprogram = 0; int isnew = 1; + int i; for(i=0;i<NUNREC;i++) hh.unrec[i] = (char *) NULL; *************** *** 85,90 int isprogram = 0; int isnew = 1; if ((hfp = fopen(file, "r")) == NULL) { printf("Can't get article.\n"); return; --- 89,97 ----- int isnew = 1; int i; + for(i=0;i<NUNREC;i++) + hh.unrec[i] = (char *) NULL; + if ((hfp = fopen(file, "r")) == NULL) { printf("Can't get article.\n"); return; *************** *** 346,351 #ifdef DEBUG fprintf(stderr, "xmit %s to %s using %s\n", file, sp->s_name, sp->s_xmit); #endif ifp = xfopen(file, "r"); if (hread(&hh, ifp, TRUE) == NULL) return; --- 353,360 ----- #ifdef DEBUG fprintf(stderr, "xmit %s to %s using %s\n", file, sp->s_name, sp->s_xmit); #endif + for(c=0;c<NUNREC;c++) + hh.unrec[c] = (char *) NULL; ifp = xfopen(file, "r"); if (hread(&hh, ifp, TRUE) == NULL) return;