bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Bug#276352: du: segfaults if you move folder(s) while it is counting


From: Jim Meyering
Subject: Re: Bug#276352: du: segfaults if you move folder(s) while it is counting
Date: Wed, 13 Oct 2004 21:24:53 +0200

Luis Lopez Lopez <address@hidden> wrote:
> Package: coreutils
> Version: 5.2.1-2
> Severity: normal
>
> The size of 'd' folder is about 100Mb like 'a' folder.
> I leave 'du' process running on a terminal and open another to do some
> work.
>
> Folder 'd' contains a big folder called 'WORK' about 80 Mb. While 'du'
> was running I move 'WORK' outside 'd'. Later I got this message when I
> suppose 'du' was ready to read 'WORK':
>
> address@hidden:~/svn$ du -hs a b c d
> 119M    a
> 11M     b
> 25M     c
> du: fts_read falló: No existe el fichero o el directorio
> Violación de segmento
>
> The message translated to english sould be something like this:
> du: fts_read falló: No such file or directory
> Segmentation fault

Thank you for the fine bug report.
It is indeed a bug in the latest sources.

I was able to reproduce it.
When a subdirectory of a du operand directory is removed
while du is traversing that subdirectory, the fts_read
function fails (as it should), but in so doing, it neglects
to set the sp->fts_cur state variable, and that causes the
subsequent fts_close to free an invalid pointer.

Here's a patch:

2004-10-13  Jim Meyering  <address@hidden>

        * fts.c (fts_read): When about to fail (by returning NULL) due
        to a failed fchdir or failed fts_safe_changedir call, set
        `sp->fts_cur = p'.  Do this by removing the explicit `return NULL;'
        statements and setting p->fts_errno so execution falls through
        to the common-case code below.  Otherwise, after such a failure,
        calling fts_close would attempt to free an already-freed buffer.
        Reported by Luis Lopez Lopez in http://bugs.debian.org/276352.

Index: lib/fts.c
===================================================================
RCS file: /fetish/cu/lib/fts.c,v
retrieving revision 1.20
diff -u -p -r1.20 fts.c
--- lib/fts.c   2 Sep 2004 23:56:59 -0000       1.20
+++ lib/fts.c   13 Oct 2004 18:13:42 -0000
@@ -716,27 +716,28 @@ name:             t = sp->fts_path + NAPPEND(p->fts
         */
        if (p->fts_level == FTS_ROOTLEVEL) {
                if (FCHDIR(sp, sp->fts_rfd)) {
+                       p->fts_errno = errno;
                        SET(FTS_STOP);
-                       return (NULL);
                }
        } else if (p->fts_flags & FTS_SYMFOLLOW) {
                if (FCHDIR(sp, p->fts_symfd)) {
                        saved_errno = errno;
                        (void)close(p->fts_symfd);
                        __set_errno (saved_errno);
+                       p->fts_errno = errno;
                        SET(FTS_STOP);
-                       return (NULL);
                }
                (void)close(p->fts_symfd);
        } else if (!(p->fts_flags & FTS_DONTCHDIR) &&
                   fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
+               p->fts_errno = errno;
                SET(FTS_STOP);
-               return (NULL);
        }
        p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
        if (p->fts_errno == 0)
                LEAVE_DIR (sp, p, "3");
-       return (sp->fts_cur = p);
+       sp->fts_cur = p;
+       return ISSET(FTS_STOP) ? NULL : p;
 }
 
 /*




reply via email to

[Prev in Thread] Current Thread [Next in Thread]