#976865 bug in glob(3) causes dash to remove trailing slash

Package:
libc6
Source:
glibc
Description:
GNU C Library: Shared libraries
Submitter:
Jeff King
Date:
2020-12-12 21:21:03 UTC
Severity:
normal
Tags:
#976865#5
Date:
2020-11-16 09:45:31 UTC
From:
To:
With the latest version of dash, I get this behavior:

  $ touch here
  $ dash -c 'printf "%s\n" "$@"' -- here/ not-here/
  here
  not-here/

The trailing slash is stripped from the argument "here/", when the file
"here" exists in the current directory (but not from "not-here/", which
does not exist).

This is rather surprising to scripts which may not even intend for their
arguments to be files (I noticed because it breaks Git's test suite,
which expects "some-script foo/" to preserve the trailing slash, which
is meaningful in its internal path matching). And certainly it differs
from the behavior of 0.5.10.2-7, which prints "here/".

Bisection points to upstream 7638476 (shell: Enable fnmatch/glob by
default, 2020-05-28). And indeed, building locally with "./configure
--disable-fnmatch" makes the problem go away. But since that commit was
only flipping the defaults, presumably the problem was already there.
Bisecting with "--enable-fnmatch --enable-glob" shows that it comes from
6900ff6 (expand: Fix glibc glob(3) support, 2018-03-26).

#976865#16
Date:
2020-11-17 03:32:03 UTC
From:
To:
Andrej Shadura <andrew@shadura.me> wrote:

This is a bug in glob(3).  Please dup and reassign to libc6.  There
is a patch in the queue to disable glob by default again.

Cheers,

#976865#37
Date:
2020-12-09 12:27:17 UTC
From:
To:
Can you please describe more precisely what is the problem with glob(3)?

Thanks,
Aurelien

#976865#42
Date:
2020-12-10 02:56:54 UTC
From:
To:
Aurelien Jarno <aurelien@aurel32.net> wrote:

It's stripping trailing slashes from the pattern, even when the
name in question is a regular file.

https://patchwork.kernel.org/project/dash/patch/20201116025222.GA28742@gondor.apana.org.au/

Cheers,

#976865#47
Date:
2020-12-10 07:58:37 UTC
From:
To:
That's the dash symptoms. glob(3) takes a pattern and just returns the
paths matching the pattern, as they are named on the filesystem. That
said, the option GLOB_MARK can return a trailing slash for all matched
path that are a directory.

#976865#52
Date:
2020-12-10 11:35:08 UTC
From:
To:
Yes but it's really a bug in glob(3).  It should really return
a no-match for the case in question, rather than matching and then
returning a filename without the slash.

IOW the pattern "foo\/" should not match a regular file foo.

Note that the problem doesn't occur for "foo/".

Cheers,

#976865#57
Date:
2020-12-10 12:12:36 UTC
From:
To:
Create a regular file called "foo", then call glob(3) with the
pattern "foo\/".  This returns a single match with the string
"foo".  This should return no match.

If you change the pattern to "foo/", then it also matches but
returns with the string "foo/" as expected.

The only flag we pass to glob(3) is GLOB_NOMAGIC.

Cheers,

#976865#62
Date:
2020-12-10 15:20:29 UTC
From:
To:
It seems like it happens for "foo/", too. If I compile:
#976865#67
Date:
2020-12-11 02:03:11 UTC
From:
To:
I think the key is that dash uses GLOB_NOMAGIC.

Cheers,

#976865#72
Date:
2020-12-11 02:05:02 UTC
From:
To:
I wondered that, too, but adding GLOB_NOMAGIC to the call doesn't seem
to change the results. This is all with libc6 2.31-5, by the way.

#976865#77
Date:
2020-12-12 21:18:10 UTC
From:
To:
* Herbert Xu:

I believe this has been reported upstream here:

  <https://sourceware.org/bugzilla/show_bug.cgi?id=25659>

(But I have not reveiwed this particular bug thread here, sorry.)