bruno@future.gipsi.fr (Bruno Verlyck) (10/12/89)
I recently found a bug in termcap.c, that could be related to a problem described by turner@uicsrd.csrd.uiuc.edu (Steve Turner): > .. then emacs dies in a call to free()! .. At least the symptom is the same. emacs-version: 18.55 Description: Near line 660 in termcap.c, the loop: while (*end && *end != '\n') end++; obviously expects a '\0' after the last (useful) byte in the buffer. But this '\0' is set only if the buffer is not full (near line 685): if (bufp->full != bufp->size) buf[bufp->full] = 0; If bufp->full == bufp->size, there is no warranty that bufp->ptr won't go past the end of the buffer. If this happens, bufp->full will become negative near line 679: bcopy (bufp->ptr, buf, bufp->full -= bufp->ptr - buf); since bufp->ptr - buf > bufp->size (max value of bufp->full). Three lines below: if (!(nread = read (fd, buf + bufp->full, bufp->size - bufp->full))) will read in memory before buf (= bufp->beg), destroying malloc info; emacs will abort later, while trying: free (buf.beg); If this may help to reproduce the bug: it happens to me after loading gnus in site-load.el (don't forget to add gnus.elc to make {etcdir}DOC in ymakefile): this lets huge doc strings in memory. Note that you also have to type emacs -nw if you are using X. Now, the minimal patch (and cleanest, I hope) I used to cure the bug. It simply allocates one more byte for the buffer, and clears it unconditionally. *** termcap.c Tue Sep 19 19:24:49 1989 --- old/termcap.c Thu Nov 24 14:00:10 1988 *************** *** 470,476 **** return -1; buf.size = BUFSIZE; ! buf.beg = (char *) xmalloc (buf.size + 1); term = indirect ? indirect : name; if (!bp) --- 470,476 ---- return -1; buf.size = BUFSIZE; ! buf.beg = (char *) xmalloc (buf.size); term = indirect ? indirect : name; if (!bp) *************** *** 667,673 **** if (bufp->full == bufp->size) { bufp->size *= 2; ! tem = (char *) xrealloc (buf, bufp->size + 1); bufp->ptr += tem - buf; append_end += tem - buf; bufp->beg = buf = tem; --- 667,673 ---- if (bufp->full == bufp->size) { bufp->size *= 2; ! tem = (char *) xrealloc (buf, bufp->size); bufp->ptr += tem - buf; append_end += tem - buf; bufp->beg = buf = tem; *************** *** 682,688 **** if (!(nread = read (fd, buf + bufp->full, bufp->size - bufp->full))) bufp->ateof = 1; bufp->full += nread; ! buf[bufp->full] = 0; } return end + 1; } --- 682,689 ---- if (!(nread = read (fd, buf + bufp->full, bufp->size - bufp->full))) bufp->ateof = 1; bufp->full += nread; ! if (bufp->full != bufp->size) ! buf[bufp->full] = 0; } return end + 1; }