Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!linus!security!genrad!grkermit!masscomp!clyde!floyd!harpo!utah-cs!lepreau From: lepreau@utah-cs.UUCP (Jay Lepreau) Newsgroups: net.bugs.4bsd Subject: scandir() calls realloc too much and is not pessimistic enuf Message-ID: <2269@utah-cs.UUCP> Date: Tue, 29-Nov-83 21:12:52 EST Article-I.D.: utah-cs.2269 Posted: Tue Nov 29 21:12:52 1983 Date-Received: Thu, 1-Dec-83 20:41:56 EST Lines: 37 Index: lib/libc/gen/scandir.c 4.2BSD Fix Description: 1. If the arraysz estimate proved low, scandir does a realloc assuming the worst, but it never recomputes the new arraysz, so it keeps calling realloc all the rest of the way thru the dir. (This isn't as bad as it sounds, for realloc is smart enuf not to do anything if the same size is requested.) 2. scandir is overly optimistic about the worst case: the directory could grow on it (unless there's some synchrony out there I don't know about), leading to an infinite loop. It should restat the directory. Repeat-By: Well, *I* noticed it from that nifty gprof output showing hundreds of realloc calls. Obvious from inspection too. Fix: *************** *** 60,61 if (++nitems >= arraysz) { names = (struct direct **)realloc((char *)names, --- 62,66 ----- if (++nitems >= arraysz) { + if (fstat(dirp->dd_fd, &stb) < 0) + return(-1); /* just might have grown */ + arraysz = stb.st_size/12; names = (struct direct **)realloc((char *)names, *************** *** 61,63 names = (struct direct **)realloc((char *)names, ! (stb.st_size/12) * sizeof(struct direct *)); if (names == NULL) --- 66,68 ----- names = (struct direct **)realloc((char *)names, ! arraysz * sizeof(struct direct *)); if (names == NULL)