dbal: [3.1.3] SQL Parser: Assertion error on long query string, caused by JIT stack limit exhaustion
BC Break Report
Q | A |
---|---|
BC Break | yes |
Version | 3.1.3 |
PHP Version | 8.0.8 |
php.ini pcre.jit | 1 |
php.ini pcre.recursion_limit | 100000 |
php.ini memory_limit | 300M |
Summary
I upgraded from 2.13.4 to 3.1.3 in an API Platform / Symfony project and got this regression in executability,
caused by: Fatal error: Uncaught AssertionError: assert($offset === strlen($sql)) in .../vendor/doctrine/dbal/src/SQL/Parser.php:105
Previous behaviour
All DQL was correctly converted to SQL and parsed+executed.
Current behavior
SQL parsing fails.
How to reproduce
Minimal reproduction repository: https://github.com/j-schumann/dbal-test
Steps:
- create a long SQL query, no parameters needed
- create a Parser instance and try to parse the long SQL -> fatal error
- reduce the SQL string length, e.g. by reducing selected fields until it works again
- set $mySQLStringEscaping = true in the Parser constructor to fail again with a shorter string, see example
It seems to be a combination of string length & used patterns, when debugging preg_match() on https://github.com/doctrine/dbal/blob/3.1.3/src/SQL/Parser.php#L95 fails when matching the following pattern:
('[^']*'|"[^"]*"|`[^`]*`|(?<!\b(?i:ARRAY))\[(?:[^\]])*\]|:{2,}|--[^\r\n]*|/\*([^*]+|\*+[^/*])*\**\*/|((?![:\?'"`\[\-\/]).)+)+
preg_last_error_msg() returns JIT stack limit exhausted
I want to emphasize that executing the DQL that caused this query worked with the same PHP version & settings in DBAL 2.13.4, that’s why I filed this as BC break.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 15 (8 by maintainers)
@j-schumann please check the implementation in https://github.com/doctrine/dbal/pull/4927.