#757404 regexec: Please validate limits when using REG_STARTEND

Package:
libc6
Source:
glibc
Description:
GNU C Library: Shared libraries
Submitter:
Christoph Biedl
Date:
2014-08-07 20:21:06 UTC
Severity:
normal
#757404#5
Date:
2014-08-07 20:17:44 UTC
From:
To:
Dear Maintainer,

when the REG_STARTEND bit is set in eflags, regexec happily accepts
anything that is set as begin and end offset of the actual string in
rm_so and rm_eo. If undefined or set to inplausible values, regexec
might take long computation times or even segfault, reproducer below,
tested in the amd64 architecture.

This happened with a certain program provided by Debian where a
programming error led to an rm_eo value of -1 und subsequently some
trouble. That application needs to be fixed of course, nevertheless
regexec should deal with such a situation in a sane way.

The fix might be as simple as (not tested)
--- a/posix/regexec.c
+++ b/posix/regexec.c
@@ -237,6 +237,8 @@ regexec (preg, string, nmatch, pmatch, eflags)
     {
       start = pmatch[0].rm_so;
       length = pmatch[0].rm_eo;
+      if (start < 0 || length < 0 || length < start)
+        return REG_BADPAT;
     }
   else
     {

Some remarks:

* Unless NUL characters are allowed in the string, an additional check
  could validate both start and length against strlen (string).
* The "length" name is confusing, I guess that should be understood
  as "end_offset".
* There is no documentation of REG_STARTEND in regex(3), so some
  details are unclear.
* The reproducer also works for wheezy and squeeze.

Regards,

    Christoph

Reproducer:


#include <regex.h>

int main (int argc, char *argv[]) {
    regex_t rx;
    regmatch_t pmatch[1];

    regcomp(&rx, "a", REG_NEWLINE);
    pmatch[0].rm_so = -223112792;
    pmatch[0].rm_eo = 32749;
    regexec(&rx, "b", 1, pmatch, REG_STARTEND);
    regfree(&rx);
}