[net.news.b] Bug fixes for expire infinite loop

pag@hao.UUCP (Peter Gross) (02/15/84)

The expire infinite loop bug was caused by two separate problems.
The problem likely only shows up on PDP-11/70's, but could eventually
occur on any non-virtual memory UNIX, as a segmentation violation.
1.  In header.c, hread() didn't check the return value of malloc()
    when it dynamically allocated memory for "unrecognized" header
    fields.  Normally this would cause a segmentation violation when
    the NULL pointer was used as a store address.  But because it was
    used as an argument to strcpy(), nothing (noticeable) happened.
    Try it, campers: strcpy(NULL, "any old string") does not cause
    a SIGSEGV (at least on PDP-11/70's when compiled sep i/d)!
2.  In expire the code reads through the existing history file,
    processing lines one at a time, checking for expiration, removing
    expired articles, remaking a new history file and associated dbm
    files.  Well as times goes on, the cumulative effect of doing
    hread()'s on articles with unrecognized header lines eventually
    uses up all the free memory.  But hread() keeps on doing its
    strcpy(h.unrec[blotto], <unrec header line>).  This drives every-
    thing bonzo .... expire blows its cookies, store() stops working,
    and somehow the article which couldn't malloc() any more memory
    starts looping in the nhistory file.  Ouch!

Here are the fixes, first to header.c and second to expire.c:
*** header.orig.c	Wed Feb 15 11:48:56 1984
--- header.c	Wed Feb 15 11:47:48 1984
***************
*** 213,218
  		case OTHER:
  			if (unreccnt < NUNREC) {
  				hp->unrec[unreccnt] = malloc(strlen(bfr) + 1);
  				strcpy(hp->unrec[unreccnt], bfr);
  				unreccnt++;
  			}

--- 215,222 -----
  		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++;
  			}

*** expire.orig.c	Wed Feb 15 11:49:29 1984
--- expire.c	Wed Feb 15 11:47:46 1984
***************
*** 211,216
  		ohfd = xfopen(ARTFILE, "r");
  		nhfd = xfopen(NARTFILE, "w");
  	}
  
  	while (TRUE) {
  		if (nohistory) {

--- 214,221 -----
  		ohfd = xfopen(ARTFILE, "r");
  		nhfd = xfopen(NARTFILE, "w");
  	}
+ 	for(i=0;i<NUNREC;i++)
+ 		h.unrec[i] = (char *) NULL;
  
  	while (TRUE) {
  		if (nohistory) {
***************
*** 292,297
  				printf("Can't open %s.\n", filename);
  			continue;
  		}
  		if (hread(&h, fp, TRUE) == NULL) {
  			if (verbose)
  				printf("Garbled article %s.\n", filename);

--- 297,312 -----
  				printf("Can't open %s.\n", filename);
  			continue;
  		}
+ 		/*
+ 		 * Prevent memory exhaustion on PDP-11's -- cumulative
+ 		 * malloc()'s of unrecognized header lines, if not free()'d,
+ 		 * could use up all of free memory
+ 		 */
+ 		for(i=0;i<NUNREC;i++)
+ 			if(h.unrec[i] != (char *) NULL)
+ 				free(h.unrec[i]);
+ 			else
+ 				break;
  		if (hread(&h, fp, TRUE) == NULL) {
  			if (verbose)
  				printf("Garbled article %s.\n", filename);
***************
*** 515,520
   	rhs.dptr = (char *) &number;
   	rhs.dsize = sizeof(number);
   
!  	store(lhs, rhs);
  #endif
  }

--- 530,536 -----
   	rhs.dptr = (char *) &number;
   	rhs.dsize = sizeof(number);
   
!  	if(store(lhs, rhs) < 0)
! 		xerror("dbm cannot store %s",article);
  #endif
  }