tech-userlevel archive

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

shell (/bin/sh) pattern matching bugs



Hi all,

I am soon going to add an ATF test for sh pattern matching (it tests all
3 forms, glob expansion, case patterns, and ${var#patern})

There are many tests, some of them quite esoteric...

First a general heads up ... the glob tests need files to match
against, and many of them ... so the test for that creates > 17000
files (all empty - other than the directories to contain them)
which means that the filesystem on which the ATF temporary
directories are made needs to have around 18000 free inodes
before the test starts (and about 1.5MiB free space for the
directories to contain the empty files).

That isn't the primary point of this mail, as I don't expect it to be
a real issue for most people (any average sized tmpfs should have
no real issue with that) - rather before committing the tests (which
currently fail) I wanted to give those of you who understand how
sh pattern matching really works a chance to challenge my interpretation
of what the results should be for the sub-tests that fail.

Note that all of the issues relate to quoting in one form or another,
so what is really in issue is how quoting and pattern matching interact.

Aside: some of this is in areas where the POSIX spec is either unclear
or simply wrong .. there has been discussion on relevant lists related to
fixing that, and eventually that will happen ... but it does mean that
simply going to the current posix spec and reading it will not necessarily
help a lot.

Another aside: the "case [ in [[:alpha:]]) ..." bug that was fixed a few days ago
in current was detected by these tests - but that one was a simple obvious sh
coding bug (copied from FreeBSD when the code to implement that kind of
thing was imported ... and yes, I did tell the FreeBSD people about it, and
their shell is also now fixed -- they actually committed the fix well before I did.)

Below I include the 14 (of 261) case pattern tests that fail in a sh from HEAD.

These are from an ATF run that includes the (currently uncommitted) new test.
The filename expansion (glob) tests have similar issues, but cannot easily be
demonsrated in an e-mail like this as without the 17000 files to see what 
should match, they are meaningless...   The var expansion pattern matching
I have not really completed writing yet (it doesn't test as much as the others,
and I am not sure when/if I ever will).   Hence only the failing case tests are here...

Note: I hand edited the ATF output to avoid noise and confusion, I think I left
the essence untouched, but ...

So below please find 14 pairs of lines (with empty lines between).   The [NNN] 
that prefixes each line is the sub-test number which is currently meaningful to
no-one but me, but here we can use those to refer to specific tests.

In each pair of lines, the first is the command that was run, and the second
says what happened and what was expected -- since all of the case test commands
either echo 'M' (when the pattern matches) or 'X' when it does not, and since these
are only the failing cases - the second line just says that M was expected and
X was obtained, or vice versa - so it gets a bit boring...

I'd appreciate it if you could look over these tests (and please consider them
carefully...) and see if you disagree with the results that the test expects.

If I have any of them wrong, I can fix them before committing the test.
Once the test is there, I will start committing fixes to sh so that the tests
eventually pass (I doubt any of these bugs are serious enough to
delay NetBSD-8 - just maybe #51 - they can be corrected in 8.0.1 or something.)

Thanks,

kre

[51] case "[a-c]" in ([a-c\]) printf M;; (*) printf X;; esac
[51] Expected output 'M', received 'X'

[97] var="[:alpha:]"; case "[" in (["$var"]) printf M;; (*) printf X;; esac
[97] Expected output 'M', received 'X'

[131] case "[x?abc" in ([[-\]]?\?*) printf M;; (*) printf X;; esac
[131] Expected output 'M', received 'X'

[132] case "]x?abc" in ([[-\]]?\?*) printf M;; (*) printf X;; esac
[132] Expected output 'M', received 'X'

[133] case "\\x?abc" in ([[-\]]?\?*) printf M;; (*) printf X;; esac
[133] Expected output 'M', received 'X'

[136] case "[]?" in ([[-\]]?\?*) printf M;; (*) printf X;; esac
[136] Expected output 'M', received 'X'

[147] var='\z'; case ${var} in (${var}) printf M;; (*) printf X;; esac
[147] Expected output 'X', received 'M'

[148] var='\z'; case ${var} in ("${var}") printf M;; (*) printf X;; esac
[148] Expected output 'X', received 'M'

[151] IFS=?; set -- a c; case abc in ("$*") printf M;; (*) printf X;; esac
[151] Expected output 'X', received 'M'

[152] IFS=?; set -- a c; case "a c" in ("$*") printf M;; (*) printf X;; esac
[152] Expected output 'X', received 'M'

[155] IFS=*; set -- a c; case abc in ("$*") printf M;; (*) printf X;; esac
[155] Expected output 'X', received 'M'

[156] IFS=*; set -- a c; case "a c" in ("$*") printf M;; (*) printf X;; esac
[156] Expected output 'X', received 'M'

[168] IFS=-; set -- a c; case b in (["$*"]) printf M;; (*) printf X;; esac
[168] Expected output 'X', received 'M'

[170] IFS=-; set -- a c; case - in (["$*"]) printf M;; (*) printf X;; esac
[170] Expected output 'M', received 'X'




Home | Main Index | Thread Index | Old Index