[pcre-dev] [Bug 2077] New: pcre2_serialize_decode() can read…

Top Page

Reply to this message
Author: admin
To: pcre-dev
Subject: [pcre-dev] [Bug 2077] New: pcre2_serialize_decode() can read from invalid memory because it does not know bytes length

            Bug ID: 2077
           Summary: pcre2_serialize_decode() can read from invalid memory
                    because it does not know bytes length
           Product: PCRE
           Version: 10.23 (PCRE2)
          Hardware: x86
                OS: Linux
            Status: NEW
          Severity: bug
          Priority: medium
         Component: Code
          Assignee: ph10@???
          Reporter: ppisar@???
                CC: pcre-dev@???

Created attachment 1006
--> https://bugs.exim.org/attachment.cgi?id=1006&action=edit
malign serialized pattern

A static analyzes revealed pcre2_serialize_decode() can experience a read from
invalid memory, if supplied serialized pattern is malformed.

The function has following code in a for-cycle. First it reads blocksize from
the serialized pattern:

  memcpy(&blocksize, src_bytes + offsetof(pcre2_real_code, blocksize),

Then it checks the value is not too small:

  if (blocksize <= sizeof(pcre2_real_code))

Then it allocates dst_re memory for blocksize bytes and, finaly, it copies the
data of the blocksize minus a header size:

  memcpy(((uint8_t *)dst_re) + sizeof(pcre2_memctl),
    src_bytes + sizeof(pcre2_memctl), blocksize - sizeof(pcre2_memctl));

Here is the problem. The memcpy() blindly trusts blocksize value and if the
value is too big, bigger than valid src_bytes memory area, the memcpy() will
read past the src_bytes memory area.

As an example, you can run this command on the attached /tmp/pattern to see an
invalid memory read:

$ printf '#load /tmp/pattern\n' | libtool --mode=execute valgrind ./pcre2test
PCRE2 version 10.30-DEV 2017-03-05
#load /tmp/pattern
==25804== Source and destination overlap in memcpy(0x623ccc8, 0x623c768, 65397)
==25804==    at 0x4C301F3: memcpy@@GLIBC_2.14 (vg_replace_strmem.c:1018)
==25804==    by 0x50F0304: pcre2_serialize_decode_8 (pcre2_serialize.c:212)
==25804==    by 0x40EF59: process_command (pcre2test.c:4503)
==25804==    by 0x41A9E3: main (pcre2test.c:7813)

The /tmp/pattern has modified blocksize value at offset 502. Original valid
value was 0x8d 0x00 0x00 0x00, current invalid value is 0x8d 0xff 0x00 0x00.
This gives bogus blocksize=65421 instead of valid 141 and instructs memcpy() to
read past the buffer.

The problem is pcre2_serialize_decode() does not validate the parsed data.

Reading the pcre2_serialize_decode() prototype:

pcre2_serialize_decode(pcre2_code **codes, int32_t number_of_codes,
const uint8_t *bytes, pcre2_general_context *gcontext)

I can see there is no length of "bytes" buffer passed to the function, thus its
impossible to do any validation.

I understand why function was written without security on mind (the serialized
pattern isn't portable and not expected to be provided from a nontrusted
party). Proper fix would require API change. If you do not consider it worth of
fixing, a decent notice in the documentation would be great. I wasn't able to
find anything in pcre2serialize about this issue.

You are receiving this mail because:
You are on the CC list for the bug.