🌐 US-Proxy
class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
Skip to content

Report invalid $flags constants for preg_replace_callback() and preg_replace_callback_array() - #6019

Merged
staabm merged 1 commit into
phpstan:2.2.xfrom
phpstan-bot:create-pull-request/patch-are3rfm
Jul 8, 2026
Merged

Report invalid $flags constants for preg_replace_callback() and preg_replace_callback_array()#6019
staabm merged 1 commit into
phpstan:2.2.xfrom
phpstan-bot:create-pull-request/patch-are3rfm

Conversation

@phpstan-bot

@phpstan-bot phpstan-bot commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

preg_replace_callback() and preg_replace_callback_array() accept an int $flags bitmask that only supports PREG_OFFSET_CAPTURE and PREG_UNMATCHED_AS_NULL, but PHPStan did not validate the constants passed there. Passing an unrelated PCRE constant (e.g. PREG_SPLIT_NO_EMPTY) went unreported. This change registers both functions in the constant-to-parameter map so invalid $flags constants are now reported.

Changes

  • resources/constantToFunctionParameterMap.php: added preg_replace_callback (flags, bitmask) and preg_replace_callback_array (flags, bitmask) entries, each allowing PREG_OFFSET_CAPTURE and PREG_UNMATCHED_AS_NULL.
  • tests/PHPStan/Rules/Functions/data/constant-parameter-check.php: added calls with a wrong constant, a correct constant, and a correct bitmask for both functions.
  • tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php: added the two expected errors.

Root cause

The recently introduced constantToFunctionParameterMap.php whitelists which constants each function's flag/mode parameter accepts. The PCRE family was only partially populated — preg_match, preg_match_all, preg_split and preg_grep were present, but the two callback-based replacers (whose $flags parameter was added in PHP 7.4) were omitted, so their flags parameter was never checked.

I probed the sibling constructs on the same axis:

  • PCRE: the only remaining functions with a constant flag parameter were preg_replace_callback and preg_replace_callback_array — both are now covered. preg_replace/preg_quote have no constant flags.
  • Other flag/mode families already in the map (JSON, sorting, HTML entities, filter, error reporting, libxml, mysqli, finfo, ...) were checked and are already complete.

Test

CallToFunctionParametersRuleTest::testConstantParameterCheck now asserts two additional errors (PREG_SPLIT_NO_EMPTY rejected for preg_replace_callback $flags and preg_replace_callback_array $flags), and confirms the correct single/bitmask constants produce no error. The test fails before the map change and passes after it. ConstantToFunctionParameterMapTest validates the new entries against reflection.

Fixes phpstan/phpstan#11437
Closes phpstan/phpstan#14910

…preg_replace_callback_array()`

- Add `preg_replace_callback` and `preg_replace_callback_array` entries to
  resources/constantToFunctionParameterMap.php, so their `$flags` bitmask
  parameters only accept `PREG_OFFSET_CAPTURE` and `PREG_UNMATCHED_AS_NULL`
  (the same constants already whitelisted for `preg_match`).
- The rest of the PCRE family (`preg_match`, `preg_match_all`, `preg_split`,
  `preg_grep`) was already covered; `preg_replace` and `preg_quote` have no
  constant flags. The other constant-flag families in the map (JSON, sorting,
  HTML entities, filter, libxml, ...) were probed and are already complete.
- Extend the constant-parameter-check regression data and test with wrong,
  single-correct and bitmask-correct `$flags` for both functions.
@staabm
staabm requested a review from VincentLanglet July 8, 2026 05:18
@staabm
staabm merged commit 670bcc1 into phpstan:2.2.x Jul 8, 2026
669 of 671 checks passed
@staabm
staabm deleted the create-pull-request/patch-are3rfm branch July 8, 2026 09:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

detect PREG_UNMATCHED_AS_NULL beeing used for wrong parameter more precise preg_replace_callback* $flags types

3 participants