PHP-CS-Fixer: `phpdoc_types_order` corrupts valid phpDoc with `array{}` syntax

Bug report

phpdoc_types_order tries to apply such changes (or other similar) to Fixer’s codebase:

     /**
-     * @var null|list<array{class-string<TestCase>}>
+     * @var null|list<array{class-sTestCasestCase>}>
      */

     /**
-     * @return iterable<array{0: string, 1: null|string, 2?: array<string, mixed>}>
+     * @return iterable<array{stringinmixed null|string, 2?: array<string, mixed>}>
      */

     /**
-     * @return iterable<array{0: string, 1?: null|string, 2?: array<string, bool>}>
+     * @return iterable<array{stringinbool?: null|string, 2?: array<string, bool>}>
      */

CC: @paulbalandan and maybe @mvorisek (parsing phpDoc?).

Runtime version

PHP CS Fixer 3.17.1-DEV Brazilian Kangaroo by Fabien Potencier and Dariusz Ruminski. PHP runtime: 8.2.4

Used command

./php-cs-fixer fix --verbose --diff --dry-run --rules=phpdoc_types_order

on this repo.

Configuration file

Default project’s config.

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 16 (12 by maintainers)

Most upvoted comments

This is not only my repository, but all RPMs (Fedora, RHEL, CentOS…)

This is an old issue related to security (SElinux) IIRC this is about the execution of code not in executable memory (data)

Also not supported on some arches:

https://src.fedoraproject.org/rpms/pcre2/blob/rawhide/f/pcre2.spec#_155 https://src.fedoraproject.org/rpms/php/blob/rawhide/f/php.spec#_880

@mvorisek I don’t need to retest - it fails in both scenarios for me, because of PCRE JIT Support => not compiled in 🤷‍♂️. It’s either because ARM architecture or asdf’s PHP builds, I don’t know. Fortunately it works through Docker setup provided in the repo 😉.

@mvhirsch repo probably not needed, as I was able to reproduce the problem with -d pcre.jit=0 localy.

That’s okay, in case you still need it: https://github.com/mvhirsch/php-cs-fixer-reproducer

@mvhirsch may I know why you have pcre.jit disabled by default or in which environment/distribution it is disabled by default?

I never thought about that. I’ve installed remi’s php packages 'cause of modularity (using multiple versions on same machine).

$> dnf info php
Installed Packages
Name         : php
Version      : 8.2.6
Release      : 1.fc37.remi
Architecture : x86_64
Size         : 5.3 M
Source       : php-8.2.6-1.fc37.remi.src.rpm
Repository   : @System
From repo    : remi-modular
Summary      : PHP scripting language for creating dynamic web sites
...

I have never configured PCRE on my machine.

php -i | grep -i pcre
pcre
PCRE (Perl Compatible Regular Expressions) Support => enabled
PCRE Library Version => 10.40 2022-04-14
PCRE Unicode Version => 14.0.0
PCRE JIT Support => enabled
PCRE JIT Target => x86 64bit (little endian + unaligned)
pcre.backtrack_limit => 1000000 => 1000000
pcre.jit => Off => Off
pcre.recursion_limit => 100000 => 100000

incase-sensitive search 🤦

I’m preparing a reproducing-repository 👍

I’m having the same issue on my Fedora 37, using PHP 8.2.6. This just started to happen a few weeks ago, but I weren’t able to find the source/change on my machine. PCRE is the first useful hint 😃

Running with -d pcre.jit=1 seems to fix the problem on my machine.

$> vendor/bin/php-cs-fixer --version
PHP CS Fixer 3.17.0 Brazilian Kangaroo by Fabien Potencier and Dariusz Ruminski.
PHP runtime: 8.2.6
$> php --version
PHP 8.2.6 (cli) (built: May  9 2023 06:25:31) (NTS gcc x86_64)
Copyright (c) The PHP Group
Zend Engine v4.2.6, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.6, Copyright (c), by Zend Technologies
$> php -i | grep pcre\.jit
pcre.jit => Off => Off

Tests fail with exact same output as in https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues/6997#issuecomment-1566067284, but running with php -d pcre.jit=1 vendor/bin/phpunit tests/DocBlock/TypeExpressionTest.php everything’s green:

php -d pcre.jit=1 vendor/bin/phpunit tests/DocBlock/TypeExpressionTest.php 
PHPUnit 9.6.8 by Sebastian Bergmann and contributors.

Testing PhpCsFixer\Tests\DocBlock\TypeExpressionTest
.....................................................................................................................................................................................................................         213 / 213 (100%)

Time: 00:00.085, Memory: 4.00 MB

OK (213 tests, 526 assertions)

I have M1, and your test does not pass for me:

 php -dpcre.jit=0 vendor/bin/phpunit tests/DocBlock/TypeExpressionTest.php
PHPUnit 9.6.8 by Sebastian Bergmann and contributors.

Testing PhpCsFixer\Tests\DocBlock\TypeExpressionTest
...................................................................................F.......F..............................................................................................F. 188 / 213 ( 88%)
.........FF..............                                                                                                                                                                    213 / 213 (100%)

Time: 00:00.046, Memory: 24.50 MB

There were 5 failures:

1) PhpCsFixer\Tests\DocBlock\TypeExpressionTest::testGetTypes with data set #83 ('array { a : int | string , b ..., C> }', array('array { a : int | string , b ..., C> }'))
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'B'
+'r'

/Volumes/Projects/~Github/PHP-CS-Fixer/PHP-CS-Fixer/tests/DocBlock/TypeExpressionTest.php:33
/Volumes/Projects/~Github/PHP-CS-Fixer/PHP-CS-Fixer/tests/DocBlock/TypeExpressionTest.php:54

2) PhpCsFixer\Tests\DocBlock\TypeExpressionTest::testGetTypes with data set #91 ('callable(array<int, string>, ...: bool', array('callable(array<int, string>, ...: bool'))
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'int'
+'le('

/Volumes/Projects/~Github/PHP-CS-Fixer/PHP-CS-Fixer/tests/DocBlock/TypeExpressionTest.php:33
/Volumes/Projects/~Github/PHP-CS-Fixer/PHP-CS-Fixer/tests/DocBlock/TypeExpressionTest.php:54

3) PhpCsFixer\Tests\DocBlock\TypeExpressionTest::testSortTypes with data set "array shape with multiple colons - callable" ('array{array{x:int|bool}, int|... void}', 'array{array{x:bool|int}, bool... void}')
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'array{array{x:bool|int}, bool|int, callable(): void}'
+'array{array{x:int|bool}, int|bool, callable(): vvoid'

/Volumes/Projects/~Github/PHP-CS-Fixer/PHP-CS-Fixer/tests/DocBlock/TypeExpressionTest.php:449

4) PhpCsFixer\Tests\DocBlock\TypeExpressionTest::testSortTypes with data set "with multiple nesting levels" ('array{0: Foo<int|bool>|Bar<ca...Bar)>}', 'array{0: Bar<callable(array<b...|int>}')
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'array{0: Bar<callable(array<bool|int>|float|string): (Bar|Foo)>|Foo<bool|int>}'
+'arrabool|int<int|bool>|Bar<callable(string|float|array<int|bool>): (Foo|Bar)>}'

/Volumes/Projects/~Github/PHP-CS-Fixer/PHP-CS-Fixer/tests/DocBlock/TypeExpressionTest.php:449

5) PhpCsFixer\Tests\DocBlock\TypeExpressionTest::testSortTypes with data set "with multiple nesting levels and callable within union" ('array{0: Foo<int|bool>|Bar<ca...|Baz>}', 'array{0: Bar<Baz|callable(arr...|int>}')
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'array{0: Bar<Baz|callable(array<bool|int>|float|string): (Bar|Foo)>|Foo<bool|int>}'
+'arrabool|int<int|bool>|Bar<callable(string|float|array<int|bool>): (Foo|Bar)|Baz>}'

/Volumes/Projects/~Github/PHP-CS-Fixer/PHP-CS-Fixer/tests/DocBlock/TypeExpressionTest.php:449

FAILURES!
Tests: 213, Assertions: 513, Failures: 5.

Same with -dpcre.jit=1.