[net.news.b] Bug fix for wasted memory use

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;