[pcre-dev] [Bug 1803] segfault in pcre jit when running twig…

Top Page
Delete this message
Author: admin
Date:  
To: pcre-dev
Subject: [pcre-dev] [Bug 1803] segfault in pcre jit when running twig test suite (PHP7)
https://bugs.exim.org/show_bug.cgi?id=1803

--- Comment #19 from Zoltan Herczeg <hzmester@???> ---
> > An empty string? But that cannot match from 2-4.
>
> I would expect that would be the pattern, based upon my understanding of
> twig.


Perhaps the runtime environment may match other patterns as well.

Btw, this pattern can also overwrite the ovector:

https://github.com/php/php-src/blob/master/ext/pcre/php_pcre.c#L1847

Since JIT is not enabled for that pattern, it could explain how -1 is appeared
in the ovector.

> So I attempted to do this a few times, but the failing &pce->re value kept
> changing between runs. Is that expected? That made the write watchpoint fail
> to trip. Any advice? Agreed we need to figure out what the pattern actually
> is.


This is bad news. Normally allocators consistently return with the same
addresses except if address (or mmap) randomization is enabled for security
reasons. I think it would take too much time to figure this out, so lets try
something simpler first.

Perhaps we should assume that the pattern is the empty string, and do a control
flow analysis. Even if count is optimized out, after pcre_exec returns, the
return value is in $rax. You can print it with "p $rax".

Count is likely $rax here:

if (count == 0)

We can confirm this by:

disassemble $pc,$pc+32

The code should start with "cmp $rax, 0", except if the value in $rax is moved
to another register by GCC.

Basically we need to check which conditional blocks are executed. Could you do
the following analysis:

Please check the executed code path for each run of the ((limit_val == -1 ||
limit_val > 1)) loop. E.g:

1st run of the loop:

count ($rax) was 2, so the (count > 0 && (offsets[1] - offsets[0] >= 0))
condition is fulfilled, and the first conditional block is executed. offsets
contains 2,2. Later g_notempty was initialized with 0.

2nd run of the loop:

this time count ($rax) was -1 (0xffffffffffffffff), and the count ==
PCRE_ERROR_NOMATCH part was executed. The offsets is overwritten by the
pcre_exec with 2,4. Later g_notempty was initialized with 0.


The following code path may not be entirely correct:

count = pcre_exec(re_bump, extra_bump, subject,
          subject_len, start_offset,
          exoptions, offsets, size_offsets);


can overwrite offsets, and later

g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED
: 0;

uses these overwritten values. I don't think this was the intention of the
author.

But the segfault may be caused by a different issue.

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