glenn@nsc.UUCP (Glenn Skinner) (03/26/84)
There is a serious bug in the filename completion code in emacs #264 that can cause emacs to core dump when reading large directories. The problem arises when reading directory entries. The code maintains two dynamically allocated arrays to hold character strings for the directory entries and to hold pointers into this flat array of strings. When either of these arrays overflows it is realloc'ed. The bug is that when the string array is reallocated, the pointers in the pointer array must be adjusted to point into the new location. The original code omits this adjustment. The fix is as follows. Line numbers will almost certainly be off. -- Glenn Skinner National Semiconductor, Microprocessor Systems Division (408) 733-2600 x 335 {amd70,fortune,hplabs,menlo70}!nsc!glenn ------------------------------- *** filecomp.c-264.1 Mon Mar 26 10:51:04 1984 --- filecomp.c-264.2 Mon Mar 26 10:51:30 1984 *************** *** 181,187 } if (KeepThisOne) { if (p -> d_namlen > ColumnWidth) ColumnWidth = p->d_namlen; ! if (BytesUsed + p -> d_namlen + 2 >= EntryNameSize) { EntryNameSize = (BytesUsed + p -> d_namlen) * 3 / 2; if (EntryNameSize < 1000) EntryNameSize = 1000; --- 181,187 ----- } if (KeepThisOne) { if (p -> d_namlen > ColumnWidth) ColumnWidth = p->d_namlen; ! if (BytesUsed + p -> d_namlen + 6 >= EntryNameSize) { EntryNameSize = (BytesUsed + p -> d_namlen) * 3 / 2; if (EntryNameSize < 1000) EntryNameSize = 1000; *************** *** 185,192 EntryNameSize = (BytesUsed + p -> d_namlen) * 3 / 2; if (EntryNameSize < 1000) EntryNameSize = 1000; ! EntryNames = EntryNames ? (char *) realloc (EntryNames, EntryNameSize) ! : (char *) malloc (EntryNameSize); } if (DirUsed >= DirSize) { DirSize = DirUsed + 50; --- 185,202 ----- EntryNameSize = (BytesUsed + p -> d_namlen) * 3 / 2; if (EntryNameSize < 1000) EntryNameSize = 1000; ! if (EntryNames) { ! char *OldEntryNames = EntryNames; ! register int bias, i; ! ! EntryNames = (char *) realloc (EntryNames, EntryNameSize); ! /* Adjust DirEnts to point into EntryNames's new home: */ ! bias = EntryNames - OldEntryNames; ! for (i = DirUsed; i; ) ! DirEnts[--i] += bias; ! } ! else ! EntryNames = (char *) malloc (EntryNameSize); } if (DirUsed >= DirSize-2) { DirSize = DirUsed + 50; *************** *** 188,194 EntryNames = EntryNames ? (char *) realloc (EntryNames, EntryNameSize) : (char *) malloc (EntryNameSize); } ! if (DirUsed >= DirSize) { DirSize = DirUsed + 50; DirEnts = DirEnts ? (char **) realloc (DirEnts, DirSize * sizeof (char *)) : (char **) malloc (DirSize * sizeof (char *)); --- 198,204 ----- else EntryNames = (char *) malloc (EntryNameSize); } ! if (DirUsed >= DirSize-2) { DirSize = DirUsed + 50; DirEnts = DirEnts ? (char **) realloc (DirEnts, DirSize * sizeof (char *)) : (char **) malloc (DirSize * sizeof (char *));