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 }