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
}