[Top][All Lists]

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

bug#16444: bug #16444: grep -r fails with "Bad file descriptor" for ming

From: David Grayson
Subject: bug#16444: bug #16444: grep -r fails with "Bad file descriptor" for mingw-w64
Date: Tue, 10 Mar 2015 22:20:28 -0700


I am encountering this bug too.  I would like to compile grep 2.21 for
Windows using mingw-w64 and Git Bash.  But the grep that I end up compiling
exhibits several bugs related to recursive operation.  To reproduce the
bugs, I made a directory called "testdir" with two empty directories named
"a" and "b" inside it.  I used "cd" to go into the testdir.

Here is a shell session showing bug A:

  $ ../src/grep.exe a -r
  c:\Users\David\Documents\grep\grep-2.21\src\grep.exe: 9: Bad file

Here is a shell session showing bug B:

  $ ../src/grep.exe a -R
  c:\Users\David\Documents\grep\grep-2.21\src\grep.exe: warning: a:
recursive directory loop
  c:\Users\David\Documents\grep\grep-2.21\src\grep.exe: warning: b:
recursive directory loop

Bug A is more important because it prevents grep from printing the desired
output, so I am focussing on it first.  I think I have narrowed it down
enough to determine that it is actually a bug in the fts implementation
from gnulib, or in one of its dependencies (like mingw-w64 of msvcrt.dll).
If I put this small block of code at the top of main, it causes the same

  { // tmphax
    program_name = "silly";
    filename = "emptydir";

    char *fts_arg[2];
    fts_arg[0] = (char *)filename;
    fts_arg[1] = NULL;
    FTS *fts = fts_open(fts_arg, fts_opts, NULL);
    printf("fts_open returned %p\n", fts);

    FTSENT *ent;
    ent = fts_read(fts);
    ent = fts_read(fts);
    printf("  fts_path=   %s\n", ent->fts_path);
    printf("  fts_accpath=%s\n", ent->fts_accpath);
    printf("  fts_name=   %s\n", ent->fts_name);
    if(ent->fts_info == FTS_ERR)
      printf("  fts_info=   FTS_ERR\n");
      suppressible_error(filename, ent->fts_errno);
    return 36;

Note that "emptydir" is a directory inside the CWD that is empty.  The
output from that block of code is:

  fts_open returned 008222B0
    fts_path=   emptydir
    fts_name=   emptydir
    fts_info=   FTS_ERR
  silly: emptydir: Bad file descriptor

I noticed that the Git repository for gnulib has some recent bug fixes for
the fts implementation, so I tried copying the fts* files from gnulib
commit 0f4fa16 into grep's lib directory, but that did not make any
difference.  My next step will probably be to take grep out of the picture
and report this as a bug to the gnulib team (or find an existing bug
report, like the one mentioned earlier in this thread).

Note that for Bug A, grep doesn't print "9" as the filename in the error
message every time.  It seems to be printing a random character that is
different each time, because grep is reading beyond the bounds of a string
and probably doing undefined behavior!  We can call that Bug C.  If a grep
maintainer is interested in fixing Bug C, they should improve the logic at
this line in grepdirent in grep.c:

  filename = ent->fts_path + filename_prefix_len;

If you run "grep a -r" then it seems that fts_path can be ".", while
filename_prefix_len is 2.  So it is really bad to execute the line above in
that case, because filename will be set to point past the end of the string
and then later used when printing error messages.

I hope this was helpful.

--David Grayson

reply via email to

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