Subject: lib/6181: fts(3) accesses free(3)'d memory
To: None <gnats-bugs@gnats.netbsd.org>
From: ITOH Yasufumi <yasufu-i@is.aist-nara.ac.jp>
List: netbsd-bugs
Date: 09/20/1998 11:41:00
>Number:         6181
>Category:       lib
>Synopsis:       fts(3) accesses free(3)'d memory
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    lib-bug-people (Library Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Sep 19 19:50:00 1998
>Last-Modified:
>Originator:     ITOH Yasufumi
>Organization:
	Nara Institute of Science and Technology, Nara, Japan
>Release:        1.3H (Sept. 18, 1998)
>Environment:
System: NetBSD acha.my.domain 1.3H NetBSD 1.3H (UVM) #4: Sun Sep 6 19:01:31 JST 1998 itohy@myname.my.domain:/usr/src/sys/arch/x68k/compile/UVM x68k


>Description:
	fts_close(3) uses memory which is already free(3)'d.

	This scarcely harms, but may cause fantastic troubles
	on multi-thread environment.

>How-To-Repeat:
	Port fts(3) and mtree(8) to Solaris and apply Purify :-).
	This is rather too hard to find with human eyes.

	Doesn't anyone have a substitution of Purify on NetBSD? (xo
	We have only a trial version which expires in a month....

>Fix:
	Note that the ISSET macro implicitly reads *sp.
	Would it be better to warn by comment?

diff -uF^[a-zA-Z_][a-z 	A-Z0-9_]*(.*[^;]$ lib/libc/gen/__fts13.c.orig lib/libc/gen/__fts13.c
--- lib/libc/gen/__fts13.c.orig	Wed Aug 19 20:08:59 1998
+++ lib/libc/gen/__fts13.c	Sun Sep 20 10:51:45 1998
@@ -240,7 +240,7 @@ fts_close(sp)
 	FTS *sp;
 {
 	FTSENT *freep, *p;
-	int saved_errno = 0;	/* pacify gcc */
+	int saved_errno = 0;
 
 	/*
 	 * This still works if we haven't read anything -- the dummy structure
@@ -265,7 +265,8 @@ fts_close(sp)
 
 	/* Return to original directory, save errno if necessary. */
 	if (!ISSET(FTS_NOCHDIR)) {
-		saved_errno = fchdir(sp->fts_rfd) ? errno : 0;
+		if (fchdir(sp->fts_rfd))
+			saved_errno = errno;
 		(void)close(sp->fts_rfd);
 	}
 
@@ -273,7 +274,7 @@ fts_close(sp)
 	free(sp);
 
 	/* Set errno and return. */
-	if (!ISSET(FTS_NOCHDIR) && saved_errno) {
+	if (saved_errno) {
 		errno = saved_errno;
 		return (-1);
 	}
>Audit-Trail:
>Unformatted: