Page MenuHomePhabricator

CSSJanus: Transformation breaks on PHP 7.x
Closed, ResolvedPublic

Description

Imported from https://github.com/cssjanus/php-cssjanus/issues/14.

We use this library at PrestaShop to perform RTL transformations onto our CSS.

Recently we became aware that some of our CSS were getting broken by this transformation.

When calling CSSJanus::transform() with a sufficiently complex/long CSS (see a specific offender here), we were getting an empty string as return value.

After some investigation, we have found that this particular regex fails, only in PHP >= 7.x, resulting in an emtpy $css:

$css = preg_replace(self::$patterns['left'], self::$patterns['tmpToken'], $css);

When printing out the last preg error:

$css = preg_replace(self::$patterns['left'], self::$patterns['tmpToken'], $css);
var_dump(preg_last_error());

...we get an error code...

int(6)

...that matches the constant PREG_JIT_STACKLIMIT_ERROR (see here).

This points out that the performed regex is overflowing the stack limit of the PCRE JIT compiler found in PHP >= 7.

I don't know if this regex can be improved, it looks pretty complex and obscure to me:

var_dump(self::$patterns['left']);
string(275) "/(?<![a-zA-Z])(left)(?![a-zA-Z])(?!(?:[!#$%&*-~]|[\200-\377]|(?:(?:(?:\[0-9a-f]{1,6})(?:\r\n|\s)?)|\[^
0-9a-f]))*?['\"]?\s*\))(?!((?:[_a-z0-9-]|[\200-\377]|(?:(?:(?:\[0-9a-f]{1,6})(?:\r\n|\s)?)|\[^>
?
|\s|#|\:|\.|\,|\+|>|\(|\)|\[|\]|=|\*=|~=|\^=|'[^']*'])*?{)/i"

A simple workaround is simply disabling the PCRE JIT compiler (with the performance impact that involves):

ini_set('pcre.jit', false);

I hope this can be fixed eventually 🙂