pbosh: case .. esac: unable to match empty string
A Tool Box with tools written or managed by Jörg Schilling
Brought to you by:
schily
The following happens with pbosh but not with bosh (tested schily-tools 2018-09-26, but I think it also happens with earlier versions).
I believe the following code should print OK, but it actually prints BAD:
pbosh -c 'x=; case $x in "") echo OK;; *) echo BAD; esac'
I also tried quoting "$x" (which shouldn't be required) - which also didn't work. The only form which did work was to prepend something like so:
case -$x in -) echo OK;; -*) echo BAD; esac
Tested on Ubuntu 18.04 LTS x64 with gcc 7.3.0, gnu make 4.1 .
All other shells which I tested, including bosh - perform as expected and print OK. I tested ksh93/dash/bash/mksh/yash/busybox-ash , and additionally also in posix-compliant mode with bash/yash/mksh.
The reason for this problem is a 30 year old hack from AT&T in _macro() together with a recent POSIX change for "case" that no longer allows to do plain "text matching" in case that the pattern matching fails.
You may check the next release (once it is ready) or apply the atached patch
Last edit: Jörg Schilling 2018-10-09
Assuming the patch refers to
sh/xec.cat the extracted source tarball (the others, includingpbosh/xec.c, seem to be symlinks to this one), I confirm the patch does fix the issue, and the test case now prints OK with pbosh. Thanks for the quick fix.Interestingly,
sh/xec.cis also used by bosh, but bosh didn't exhibit the issue (and still prints OK also with the patch). Was that expected?As for your comment about a recent change in POSIX. Being able to match the null string does seem kind of obvious (to me), and does show up in examples, and all other shells I tried do match it, but I couldn't find how to deduce it from the spec (Issue 7, 2018 edition).
Would you mind pointing out at which revision this behavior became mandated, and what wording in the spec mandates it?
Thanks
obosh does not set the strict POSIX mode and thus (for compatibility reasons) still supports the strcmp() call including a previous quote removal in case that the pattern matcher does not give a match.
BTW: ksh88 and ksh93 still include this additional strcmp() call, but I asked David Korn in April 2018 about his impression for this problem. April 2018 is when the problem has been discussed in the POSIX teleconference call, so it is not yet in a final standard. It will become an approved standard if we ever release a SUSv7 TC3, or with SUSv8.
Interesting, so technically the current POSIX spec doesn't mandate matching an empty string. But it doesn't forbid it either, right?
I also now tested with
bosh -o posix -c ...and indeed it also prints BAD before the patch, and prints OK with the patch.I guess I should have realized it might be as designed, considering
sh/sh.1has the following statement regardingcase:However, I only checked it now, while I should have checked it before reporting.
Are there cases other than the null string where this comment applies?
Last edit: Avi Halachmi 2018-10-09
The POSIX change is not related to empty strings but to the fact that
casedid first call gmatch() and if that did not match, it tried strcmp().This change together with the AT&T hack from the 1980s cause the empty string to become "\", which is an escaped nul byte that does not match using gmatch() only. In case that strcmp() is used as well, the second string is quote removed before and becomes an empty string that matches.
Last edit: Jörg Schilling 2018-10-09
Sorry for the late ping, but I just re-read all your replies, and it's still not clear to what this line should print according to POSIX:
As I mentioned I've seen empty string pattern in examples, and I would like to know whether or not it should be valid and well defined according to POSIX, regardless of bugs and regadless of the specific shell being used. I.e. just according to what's specified.
Thanks again
This is expected to print OK.
Since POSIX requires special handling for usage of shell variables, this case $x results in an empty string.
Even the new bash5 prints OK with this example and bash5 has some problems with variable quiting caused by an ongoing diskussion in the POSIX team.
Last edit: Jörg Schilling 2019-07-10
Much appreciated.
So the issue where it originally did not print OK was a bug in pbosh only?