BUG: An empty regex is not allowed in the POSIX grammar.

Thorsten Wißmann edu at thorsten-wissmann.de
Mon Apr 20 12:04:01 CEST 2020

Dear Lucas and Florian,

On Mon, Apr 20, 2020 at 03:29:10AM +0000, Lucas wrote:
> Am Lucas, and together with Florian, cc'd in this email, we're trying
> to port 0.8.0 release to OpenBSD.

thanks for porting hlwm to OpenBSD and for spotting this issue! :-)
I've fixed this in the hlwm code base:


I'm also mentioning your names and e-mail addresses, I hope this is OK
for you (I can still change it).

> Now, RegexStr::fromStr creates a POSIX Extended Regular Expression from
> the string passed. According to POSIX[1], an ERE can't be empty. In this
> regard, OpenBSD is doing the technically correct thing, but it renders
> hlwm useless!

I wasn't aware of this, thanks!

> Following this email is a diff for changing "" into "^$", which is my
> guess of what the author meant to express with an empty regex. My
> interpretation might be incorrect, or empty strings might want to be
> deal with directly inside fromStr. This is just a proposed approach.

For us, the regex "" represents an inactive regex, so there is actually
no need for us to compile it. Unfortunately, it is not a correct fix to
replace it by "^$" (Setting 'keymask' to "^$" disables all keybindings
because the setting means that the only those keybindings are active
that match "^$")

I've backported the crucial parts of the fix to v0.8.0 and I'm attaching
a patch.


-------------- next part --------------
From b4a875f303adabe4eba3f73ee7be609d1e1653e3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thorsten=20Wi=C3=9Fmann?= <edu at thorsten-wissmann.de>
Date: Mon, 20 Apr 2020 11:11:13 +0200
Subject: [PATCH] Never compile a regex for the empty string

An empty string is not allowed in the Posix grammar for extended regular
expressions. On openbsd, this led to a run time error on startup
because we initialize the keymask regexes with the empty string.

In the keymask code, we are using the empty string anyway as a special
case for an 'inactive' or 'unset' regular expression, so there is no
need to compile the regex for "".

Thanks to Lucas <lucas at sexy.is> and Florian Viehweger
<openbsd at out-of-creativity.de> for spotting and reporting this issue.

This is backportet to v0.8.0, for the full commit see
 src/regexstr.cpp | 20 +++++++++++++++-----

diff --git a/src/regexstr.cpp b/src/regexstr.cpp
index bad22701..82c2eb3e 100644
--- a/src/regexstr.cpp
+++ b/src/regexstr.cpp
@@ -11,10 +11,16 @@ RegexStr RegexStr::fromStr(const std::string &source)
     RegexStr r;
     r.source_ = source;
-    try {
-        r.regex_ = std::regex(source, std::regex::extended);
-    }  catch (const std::exception& e) {
-        throw std::invalid_argument(e.what());
+    // An empty regex is not allowed in the POSIX grammar
+    // as one can infer from the grammar at
+    // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_05_03
+    // => So we must not compile "" to a regex
+    if (!source.empty()) {
+        try {
+            r.regex_ = std::regex(source, std::regex::extended);
+        }  catch (const std::exception& e) {
+            throw std::invalid_argument(e.what());
+        }
     return r;
@@ -26,7 +32,11 @@ bool RegexStr::operator==(const RegexStr& other) const
 bool RegexStr::matches(const std::string& str) const
-    return std::regex_match(str, regex_);
+    if (source_.empty()) {
+        return false;
+    } else {
+        return std::regex_match(str, regex_);
+    }
 template<> RegexStr Converter<RegexStr>::parse(const std::string& source) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <https://listi.jpberlin.de/pipermail/hlwm/attachments/20200420/e065c231/attachment.asc>

More information about the hlwm mailing list