diff options
author | Elliott Hughes <enh@google.com> | 2019-07-24 16:12:34 -0700 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2019-07-29 06:14:55 -0500 |
commit | e4dd5350882fde0cc82741e9b424037f35887f96 (patch) | |
tree | 4339470ca9d6ef9089f73356c5d10f5edf41af9b | |
parent | 71bdf7a5ac09e4b52265b782623071b1cc6d32d7 (diff) | |
download | toybox-e4dd5350882fde0cc82741e9b424037f35887f96.tar.gz |
grep: fake GNU behavior for non-POSIX empty regex.
POSIX says there's no such thing as an empty regular expression. The
grammar excludes the possibility:
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html
BSD agrees with POSIX, and Android and macOS' BSD-based implementations
reject the empty regular expression.
GNU apparently disagrees.
Luckily, BSD does accept the empty *sub* expression `()`, despite their
error message for REG_EMPTY being "empty (sub)expression". This is
presumably a bug, except there's explicit code to support it that is at
least 26 years old:
https://github.com/freebsd/freebsd/blame/master/lib/libc/regex/regcomp.c#L383
This workaround also works fine with glibc.
If we want GNU behavior, I'm struggling to come up with another way to
fake it. If we want POSIX behavior, we could easily just add a check to
reject "" on glibc.
Also switch to xregcomp().
-rw-r--r-- | toys/posix/grep.c | 11 |
1 files changed, 3 insertions, 8 deletions
diff --git a/toys/posix/grep.c b/toys/posix/grep.c index 6fd6bd2f..f2ab2a0d 100644 --- a/toys/posix/grep.c +++ b/toys/posix/grep.c @@ -398,20 +398,15 @@ static void parse_regex(void) TT.e = list; if (!FLAG(F)) { - int i; - // Convert regex list for (al = TT.e; al; al = al->next) { struct reg *shoe; if (FLAG(o) && !*al->arg) continue; dlist_add_nomalloc(&TT.reg, (void *)(shoe = xmalloc(sizeof(struct reg)))); - i = regcomp(&shoe->r, al->arg, - (REG_EXTENDED*!!FLAG(E)) | (REG_ICASE*!!FLAG(i))); - if (i) { - regerror(i, &shoe->r, toybuf, sizeof(toybuf)); - error_exit("bad REGEX '%s': %s", al->arg, toybuf); - } + // BSD regcomp doesn't support empty regex, so we fake that. + xregcomp(&shoe->r, *al->arg ? al->arg : "()", + (REG_EXTENDED*(!!FLAG(E)|!*al->arg))|(REG_ICASE*!!FLAG(i))); } dlist_terminate(TT.reg); } |