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)

Most upvoted comments

@j-schumann please check the implementation in https://github.com/doctrine/dbal/pull/4927.