[MDEV-14640] can't build with system pcre / pcre_stack_guard not implemented Created: 2017-12-13  Updated: 2017-12-15  Resolved: 2017-12-15

Status: Closed
Project: MariaDB Server
Component/s: Compiling
Affects Version/s: 10.2.11
Fix Version/s: N/A

Type: Bug Priority: Critical
Reporter: Marc Assignee: Sergei Golubchik
Resolution: Not a Bug Votes: 0
Labels: None
Environment:

mageia cauldron



 Description   

cmake checks for pcre_stack_guard:

CHECK_LIBRARY_EXISTS(pcre pcre_stack_guard "" HAVE_PCRE_STACK_GUARD)

this check always results in a Segmentation fault, since pcre_stack_guard should point to a function which checks if the stack is correct.

If the idea is, to detect stack problems, this has to be implemented by mariadb no matter if the bundled pcre or the external is used.

The message "system pcre is not found or unusable" doesn't tell much what was wrong here.



 Comments   
Comment by Sergei Golubchik [ 2017-12-13 ]

I don't think it's the case.

pcre_stack_guard was suppored by pcre for years, it should not be a problem unless you have a very old pcre.

You cannot build with a system pcre because of a new check PCRE_STACK_SIZE_OK. It was added only recently in MDEV-13412.

Because pcre returns hugely incorrect values for the stack frame size estimates, MariaDB doesn't know when to stop the recursion and one can crash the server by using too deep recursion and trashing the stack.

cmake checks if pcre stack frame size estimate looks ok, and resorts to the bundled pcre if it doesn't.

Comment by Marc [ 2017-12-13 ]

it would be great if you don't close the bug, before I can answer:

system pcre is the same as the shipped.

Please try your check on the shipped pcre.

pcre_stack_guard is defined as NULL, so calling/checking this function always will fail!

Comment by Sergei Golubchik [ 2017-12-13 ]

Indeed, it crashes, you're right.

When I'm trying the check I see

-- Looking for pcre_stack_guard in pcre
-- Looking for pcre_stack_guard in pcre - found

And looking into /usr/share/cmake/Modules/CheckLibraryExists.cmake I see that it does try_compile not try_run. That is, cmake doesn't try to run the executable, and it doesn't care whether it crashes or not.

Until MDEV-13412 system pcre was used just fine.

By the way, if you think this bug report should be reopened, I can do it for you.

Comment by Marc [ 2017-12-13 ]

please do, I don't see any button to reopen this bug.
For now I can disable the check, but I think it would be better to have the check corrected,so anybody can compile mariadb against the system pcre.

Comment by Sergei Golubchik [ 2017-12-13 ]

You misunderstood. The check is there for a reason.

pcre_stack_guard succeeds. But PCRE_STACK_SIZE_OK fails. Because your system pcre reports unrealistically low stack frame size value. For example, my system pcre:

$ pcretest -m -C
...
  Match recursion uses stack: approximate frame size = 4 bytes

This is wrong, the size must be about 500 bytes.

Comment by Marc [ 2017-12-13 ]

I can confirm this value of 4, in pcretest.
But if I'm not mistaken, this only states, we have an extra 4 bytes as "guard" on each frame pushed to the stack. It does not state the recursion is limited in any way.
The recursion is limited (at compile time) to 1.000.0000 (Default recursion depth limit) and due to the usage of the stack, we don't need any extra reserved space.

So, what is done? Do you update the test? But at least reopen this bug.

Comment by Sergei Golubchik [ 2017-12-13 ]

No, 4 bytes is not a guard, see man pcrestack:

  The actual amount of stack used per recursion can  vary  quite  a  lot,
  depending on the compiler that was used to build PCRE and the optimiza‐
  tion or debugging options that were set for it. The rule of thumb value
  of  500  bytes  mentioned  above  may be larger or smaller than what is
  actually needed. A better approximation can be obtained by running this
  command:
 
    pcretest -m -C
 
  The  -C  option causes pcretest to output information about the options
  with which PCRE was compiled. When -m is also given (before -C), infor‐
  mation about stack use is given in a line like this:
 
    Match recursion uses stack: approximate frame size = 640 bytes
 
  The value is approximate because some recursions need a bit more (up to
  perhaps 16 more bytes).

MariaDB determines the recursion depth by dividing the thread stack size by the pcre frame size. If pcre reports the value that is too low, recursion depth will be set too high and a specially crafted regular expression can corrupt the stack.

That is, we have to know the correct pcre frame size. If system pcre lies, we'll have to use the bundled one.

Comment by Marc [ 2017-12-13 ]

I've looked into this issue directly in the pcre sources.
The reported frame size is really the size stored on the stack for one recursion.

If checked the value of 4 is correct, if pcre is compiled with -O2 or higher.
The used stack size is only determined correctly, if it is compiled with -O0.

So I think, using or checking this size, is almost useless.

Comment by Marc [ 2017-12-13 ]

The code used to determine the stack size is almost equal to this call:

static int match(char* eptr, const char *ecode,   char* mstart, int offset_top, char *md, char *eptrb,  unsigned int rdepth){
char somevars[100];
if (ecode == NULL)  {
  if (rdepth == 0)
    return match((char*)&rdepth, NULL, NULL, 0, NULL, NULL, 1);
  else    {
    int len = (int)((char *)&rdepth - (char *)eptr);
    return (len > 0)? -len : len;
    }
  }
}

The optimizer uses a short path around all variable declariations,so the result on the stack is only 4 bytes.

Comment by Sergei Golubchik [ 2017-12-14 ]

Yes. MariaDB needs to know the frame size to determine the safe recursion depth limit. For this we use a documented pcre method, as mentioned in man pcreapi. In -O2 builds this documented method returns meaningless results — so it is clearly a bug in pcre, the behavior contradicts the documentation.

I have fixed this bug in out bundled pcre copy and reported it upstream — see https://bugs.exim.org/show_bug.cgi?id=2173 — I also explain there what compiler does exactly to end up with the value of 4.

Our cmake only checks whether a system pcre behaves as documented. If yes ­— system pcre is used, if not — bundled one.

That depends on the distribution. Some distros fixed their system pcre. If Mageia will do the same, MariaDB will use system pcre there too.

Comment by Marc [ 2017-12-14 ]

Thanks for your link to the patch, if I had known you already ran into this,I would have fixed prce earlier.

Now pcre reports sth. more apropreatem, so the lib is found. Interestingly I still can't compile, since mroonga raises an internal gcc error, but that has nothing to do with this bug...

Comment by Sergei Golubchik [ 2017-12-15 ]

It was mentioned in another bug report that one can get lto1: internal compiler error: Segmentation fault when using gcc from Fedora Rawhide, while gcc from Fedora 27 works.So if you're using a particularly new gcc with some distro patches on top, it may be worth trying an older build.

Generated at Thu Feb 08 08:15:09 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.