Page MenuHome GnuPG

Bug in regexp library may lead to out-of-bounds read
Closed, ResolvedPublic

Description

The compiler in the bundled regular expression library allows any character to end a POSIX character class expression. Besides incorrect parsing, this can involve skipping the string terminator in the face of a malformed expression.
Test case:

#include "jimregexp.h"

int
main (void)
{
  regex_t r;
  return !regcomp (&r, "[[:digit:\0]", 0);
}

Trivial fix:

diff --git a/regexp/jimregexp.c b/regexp/jimregexp.c
index 7fd6d473e..1a8b8aae6 100644
--- a/regexp/jimregexp.c
+++ b/regexp/jimregexp.c
@@ -795,7 +795,8 @@ static int regatom(regex_t *preg, int *flagp)
 
                                        for (cc = 0; cc < CC_NUM; cc++) {
                                                n = strlen(character_class[cc]);
-                                               if (strncmp(pattern, character_class[cc], n) == 0) {
+                                               if (strncmp(pattern, character_class[cc], n) == 0
+                                                    && pattern[n] == ']') {
                                                        /* Found a character class */
                                                        pattern += n + 1;
                                                        break;

I have not investigated whether this has any impact on current versions of GnuPG.

Event Timeline

Another miscellaneous correction for jimregexp. A condition was copy-pasted from another section without the necessary changes, resulting in incorrect logic. This seems harmless apart from inconsistent error reporting.

diff --git a/regexp/jimregexp.c b/regexp/jimregexp.c
index 1a8b8aae6..1b6e1b49c 100644
--- a/regexp/jimregexp.c
+++ b/regexp/jimregexp.c
@@ -778,7 +778,7 @@ static int regatom(regex_t *preg, int *flagp)
                                                        preg->err = REG_ERR_NULL_CHAR;
                                                        return 0;
                                                }
-                                               if (start == '\\' && *pattern == 0) {
+                                               if (end == '\\' && *pattern == 0) {
                                                        preg->err = REG_ERR_INVALID_ESCAPE;
                                                        return 0;
                                                }
werner triaged this task as High priority.
werner edited projects, added gnupg22, gnupg24; removed gnupg.
werner added subscribers: gniibe, werner.

@gniibe, will you be so kind an check the provided patches

werner moved this task from Backlog to QA on the gnupg22 board.

Okay, that was easy to check.

werner moved this task from QA to gnupg-2.4.1 on the gnupg24 board.
werner edited projects, added gnupg24 (gnupg-2.4.1); removed gnupg24.
werner moved this task from QA to gnupg-2.2.42 on the gnupg22 board.
werner edited projects, added gnupg22 (gnupg-2.2.42); removed gnupg22.

I checked the upstream. For the reported issue, upstream version raises an error with REG_ERR_UNMATCHED_BRACKET.
That behavior is better (as we don't have particular reason to maintain different behavior from upstream version).
Also, I found another change from upstream for end of word check.

I'm going to incorporate those change.