Opened 3 years ago

Closed 3 years ago

#11472 closed Bugs (fixed)

Regex posix api reads from uninitialized memory

Reported by: lessandro@… Owned by: John Maddock
Milestone: To Be Determined Component: regex
Version: Boost Development Trunk Severity: Problem
Keywords: Cc:

Description

By running the boost test suite through our tool, Pareon Verify, I got the following report:

===== PAREON VERIFY =====
[M0203] Read(s) from uninitialized stack object detected:
  the read in
    function regcompW at /data/lessandro/boost-libcxx/libs/regex/src/wide_posix_api.cpp:81
    called from function main at /data/lessandro/boost-libcxx/libs/regex/test/c_compiler_checks/wide_posix_api_check.cpp:44
    called from function main_thread
  performed 1 access(es) of size 4 at the start of
  the stack object of size 40 allocated as `re' in
    function main at /data/lessandro/boost-libcxx/libs/regex/test/c_compiler_checks/wide_posix_api_check.cpp:42
    called from function main_thread
  and the resulting value is used in evaluating the condition in
    function regcompW at /data/lessandro/boost-libcxx/libs/regex/src/wide_posix_api.cpp:81
    called from function main at /data/lessandro/boost-libcxx/libs/regex/test/c_compiler_checks/wide_posix_api_check.cpp:44
    called from function main_thread

While this bug is harmless in that specific file (wide_posix_api_check.cpp), it does reveal an important design problem in the regex library: the use of magic values to determine if a struct has been initialized or not.

If an attacker is able to control the contents of the stack prior to the execution of regcomp, they could exploit this bug and cause a denial of service in the program.

For example, consider the following snippet, which fills the stack with the magic value and causes a crash when the program is executed.

#include <boost/regex.h>

void f()
{
        // user-modifiable data
        unsigned int s[64];
        for (int i=0; i<64; i++)
                s[i] = 25631;
}

void g()
{
        regex_t re;
        regcomp(&re, "test", 0);
        regfree(&re);
}

int main()
{
        f();
        g();
        return 0;
}

The safest thing to do is to assume that the struct is always uninitialized, and never read before writing in regcomp.

Change History (1)

comment:1 Changed 3 years ago by John Maddock

Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.