From e4dd5350882fde0cc82741e9b424037f35887f96 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Wed, 24 Jul 2019 16:12:34 -0700 Subject: 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(). --- toys/posix/grep.c | 11 +++-------- 1 file 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); } -- cgit v1.2.3