php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #74210 RegExp pattern doesn't match as expected.
Submitted: 2017-03-06 11:13 UTC Modified: 2017-03-06 11:37 UTC
From: grgtvs at gmail dot com Assigned:
Status: Not a bug Package: PCRE related
PHP Version: 7.0.16 OS: Linux kerne; 4.8.0-36-generic
Private report: No CVE-ID: None
 [2017-03-06 11:13 UTC] grgtvs at gmail dot com
Description:
------------
The pattern '/{(?:[^{}]|(?R))*}/' doesn't match anything under php7 (7.0.15) while using php 5.5.9 it matches the message succesfully.

Test script:
---------------
<?php

$re = '/{(?:[^{}]|(?R))*}/';
$str = "{\"message\":\"cURL error 7: Failed to connect to 172.17.0.1 port 3000: Connection refused\",\"trace\":\"#0 /foo/bar/vendor/guzzlehttp/guzzle/src/Adapter/Curl/CurlAdapter.php(112): GuzzleHttp\Event\RequestEvents::emitError(Object(GuzzleHttp\Adapter\Transaction), Object(GuzzleHttp\Exception\AdapterException), Array)\n#1 /foo/bar/vendor/guzzlehttp/guzzle/src/Adapter/Curl/CurlAdapter.php(91): GuzzleHttp\Adapter\Curl\CurlAdapter->handleError(Object(GuzzleHttp\Adapter\Transaction), Array, Resource id #16)\n#2 /foo/bar/vendor/guzzlehttp/guzzle/src/Client.php(193): GuzzleHttp\Adapter\Curl\CurlAdapter->send(Object(GuzzleHttp\Adapter\Transaction))\n#3 /foo/bar/vendor/guzzlehttp/guzzle/src/Client.php(181): GuzzleHttp\Client->send(Object(GuzzleHttp\Message\Request))\n#4 /foo/bar/components/react/react.php(176): GuzzleHttp\Client->post('/project/666...', Array)\n#5 /foo/bar/components/react/react.php(136): react->rendererQuery('project', '{}', Array)\n#6 /foo/bar/controllers/ProjectController.php(50): react->render('project')\n#7 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(4126): ProjectController->actionIndex()\n#8 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(3639): CInlineAction->runWithParams(Array)\n#9 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(6815): CController->runAction(Object(CInlineAction))\n#10 /foo/bar/components/Controller.php(578): CFilterChain->run()\n#11 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(6857): Controller->filterEnsureSSL(Object(CFilterChain))\n#12 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(6812): CInlineFilter->filter(Object(CFilterChain))\n#13 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(6824): CFilterChain->run()\n#14 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(4017): CFilter->filter(Object(CFilterChain))\n#15 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(6857): CController->filterAccessControl(Object(CFilterChain))\n#16 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(6812): CInlineFilter->filter(Object(CFilterChain))\n#17 /foo/bar/components/Controller.php(258): CFilterChain->run()\n#18 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(6857): Controller->filterEnsureCanonicalHost(Object(CFilterChain))\n#19 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(6812): CInlineFilter->filter(Object(CFilterChain))\n#20 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(3629): CFilterChain->run()\n#21 /foo/bar/components/Controller.php(357): CController->runActionWithFilters(Object(CInlineAction), Array)\n#22 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(3614): Controller->runActionWithFilters(Object(CInlineAction), Array)\n#23 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(1761): CController->run('index')\n#24 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(1681): CWebApplication->runController('project/index')\n#25 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(1202): CWebApplication->processRequest()\n#26 /foo/bar/www/index.php(18): CApplication->run()\n#27 {main}\",\"json_encoded\":true}";

preg_match($re, $str, $matches);

// Print the entire match result
print_r($matches);


Expected result:
----------------
Array
(
    [0] => {"message":"cURL error 7: Failed to connect to 172.17.0.1 port 3000: Connection refused","trace":"#0 /foo/bar/vendor/guzzlehttp/guzzle/src/Adapter/Curl/CurlAdapter.php(112): GuzzleHttp\Event\RequestEvents::emitError(Object(GuzzleHttp\Adapter\Transaction), Object(GuzzleHttp\Exception\AdapterException), Array)
#1 /foo/bar/vendor/guzzlehttp/guzzle/src/Adapter/Curl/CurlAdapter.php(91): GuzzleHttp\Adapter\Curl\CurlAdapter->handleError(Object(GuzzleHttp\Adapter\Transaction), Array, Resource id #16)
#2 /foo/bar/vendor/guzzlehttp/guzzle/src/Client.php(193): GuzzleHttp\Adapter\Curl\CurlAdapter->send(Object(GuzzleHttp\Adapter\Transaction))
#3 /foo/bar/vendor/guzzlehttp/guzzle/src/Client.php(181): GuzzleHttp\Client->send(Object(GuzzleHttp\Message\Request))
#4 /foo/bar/components/react/react.php(176): GuzzleHttp\Client->post('/project/666...', Array)
#5 /foo/bar/components/react/react.php(136): react->rendererQuery('project', '{}', Array)
#6 /foo/bar/controllers/ProjectController.php(50): react->render('project')
#7 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(4126): ProjectController->actionIndex()
#8 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(3639): CInlineAction->runWithParams(Array)
#9 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(6815): CController->runAction(Object(CInlineAction))
#10 /foo/bar/components/Controller.php(578): CFilterChain->run()
#11 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(6857): Controller->filterEnsureSSL(Object(CFilterChain))
#12 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(6812): CInlineFilter->filter(Object(CFilterChain))
#13 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(6824): CFilterChain->run()
#14 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(4017): CFilter->filter(Object(CFilterChain))
#15 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(6857): CController->filterAccessControl(Object(CFilterChain))
#16 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(6812): CInlineFilter->filter(Object(CFilterChain))
#17 /foo/bar/components/Controller.php(258): CFilterChain->run()
#18 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(6857): Controller->filterEnsureCanonicalHost(Object(CFilterChain))
#19 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(6812): CInlineFilter->filter(Object(CFilterChain))
#20 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(3629): CFilterChain->run()
#21 /foo/bar/components/Controller.php(357): CController->runActionWithFilters(Object(CInlineAction), Array)
#22 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(3614): Controller->runActionWithFilters(Object(CInlineAction), Array)
#23 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(1761): CController->run('index')
#24 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(1681): CWebApplication->runController('project/index')
#25 /foo/bar/lib/pph-yii-repo/framework/yiilite.php(1202): CWebApplication->processRequest()
#26 /foo/bar/www/index.php(18): CApplication->run()
#27 {main}","json_encoded":true}
)


Actual result:
--------------
Array
(
)


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-03-06 11:37 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2017-03-06 11:37 UTC] requinix@php.net
PHP 7 introduces PCRE's JIT, which can affect how a regex compiles and matches.
http://sljit.sourceforge.net/pcre.html

JIT is causing your regex to fail, as shown by the preg_last_error() code:
https://3v4l.org/F5A9p
This is due to a simple inefficiency in the regex:
  /{(?:[^{}]|(?R))*}/
           ^
Making that character set repeatable removes the problem. https://3v4l.org/OTdvX
If all else fails you can disable JIT with pcre.jit=0. https://3v4l.org/Hf2gT


Note that your regex can fail if any of the strings contains an unbalanced { }. Decoding the string as JSON is a much better solution.
 [2017-03-09 13:16 UTC] grgtvs at gmail dot com
Thanks a lot requinix, you are correct.
 
PHP Copyright © 2001-2022 The PHP Group
All rights reserved.
Last updated: Mon Jan 24 21:03:34 2022 UTC