aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2019-07-24 16:12:34 -0700
committerRob Landley <rob@landley.net>2019-07-29 06:14:55 -0500
commite4dd5350882fde0cc82741e9b424037f35887f96 (patch)
tree4339470ca9d6ef9089f73356c5d10f5edf41af9b
parent71bdf7a5ac09e4b52265b782623071b1cc6d32d7 (diff)
downloadtoybox-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.c11
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);
}