Skip to content

Declare mutually exclusive constant groups for json_encode, json_decode, filter_var, filter_input, openlog and ZipArchive::open flags - #6571

Merged
staabm merged 2 commits into
phpstan:2.3.xfrom
phpstan-bot:create-pull-request/patch-8d54l49
Sep 24, 2026
Merged

staabm merged 2 commits into
phpstan:2.3.xfrom
phpstan-bot:create-pull-request/patch-8d54l49

Conversation

@phpstan-bot

Copy link
Copy Markdown
Collaborator

Summary

PHPStan can already report constants that should not be combined in a bitmask parameter (argument.exclusiveConstants). But resources/constantToFunctionParameterMap.php only listed such groups for a few functions (sort functions, preg_match_all, htmlspecialchars, flock, mysqli, PDO, FilesystemIterator). This PR adds the groups that were missing. For example, json_decode(..., JSON_INVALID_UTF8_IGNORE | JSON_INVALID_UTF8_SUBSTITUTE) from the issue is now reported.

Changes

All data changes are in resources/constantToFunctionParameterMap.php:

  • json_encode / json_decode $flags: JSON_INVALID_UTF8_IGNORE and JSON_INVALID_UTF8_SUBSTITUTE. When both are set, IGNORE wins without any warning.
  • json_encode $flags: JSON_PARTIAL_OUTPUT_ON_ERROR and JSON_THROW_ON_ERROR. With partial output set, php-src never throws, so JSON_THROW_ON_ERROR has no effect.
  • filter_var / filter_input $options: FILTER_REQUIRE_SCALAR and FILTER_REQUIRE_ARRAY. With both set, every input fails.
  • openlog $flags: LOG_NDELAY and LOG_ODELAY. One opens the connection immediately, the other delays it.
  • ZipArchive::open $flags: ZipArchive::RDONLY and ZipArchive::OVERWRITE. libzip rejects ZIP_RDONLY | ZIP_TRUNCATE with ZIP_ER_RDONLY.

Not added:

  • FILTER_NULL_ON_FAILURE | FILTER_THROW_ON_FAILURE: FilterVarRule (filterVar.nullOnFailureAndThrowOnFailure) already reports this. A group here would report it a second time.
  • The other bitmask parameters in the map: preg_*, file, file_put_contents, glob, fnmatch, finfo*, stream_socket_*, socket_*, idn_*, openssl_pkcs7_*, iconv_mime_decode*, ob_start, msg_receive, debug_backtrace, dns_get_record, DatePeriod, and the libxml options. I went through them and found no flags that contradict each other. Some combinations are only redundant, e.g. FILEINFO_MIME together with FILEINFO_MIME_TYPE, or DNS_ALL together with specific record types.

Root cause

The exclusive-group check (ParameterAllowedConstants::check(), which FunctionCallParametersCheck reports) was already in place. The map simply had no exclusive-group data for these parameters.

Test

  • tests/PHPStan/Rules/Functions/data/bug-15306.php (CallToFunctionParametersRuleTest::testBug15306) covers json_decode, json_encode, filter_var, filter_input and openlog. It includes cases that must be reported and valid combinations that must not be.
  • tests/PHPStan/Rules/Methods/data/bug-15306.php (CallMethodsRuleTest::testBug15306) covers ZipArchive::open.
  • Both tests fail without the map change and pass with it.

Fixes phpstan/phpstan#15306

🤖 Generated with Claude Code

staabm and others added 2 commits September 24, 2026 10:21
…ecode`, `filter_var`, `filter_input`, `openlog` and `ZipArchive::open` flags

- json_encode/json_decode $flags: JSON_INVALID_UTF8_IGNORE and
  JSON_INVALID_UTF8_SUBSTITUTE are exclusive (IGNORE silently wins)
- json_encode $flags: JSON_PARTIAL_OUTPUT_ON_ERROR and JSON_THROW_ON_ERROR are
  exclusive (partial output makes php-src skip the throw)
- filter_var/filter_input $options: FILTER_REQUIRE_SCALAR and
  FILTER_REQUIRE_ARRAY are exclusive (every input fails)
- openlog $flags: LOG_NDELAY and LOG_ODELAY are exclusive
- ZipArchive::open $flags: ZipArchive::RDONLY and ZipArchive::OVERWRITE are
  exclusive (libzip rejects ZIP_RDONLY | ZIP_TRUNCATE)
- Not added: FILTER_NULL_ON_FAILURE | FILTER_THROW_ON_FAILURE. FilterVarRule
  already reports it, so a group here would report it twice.
- Checked the other bitmask parameters in the map (preg_*, file,
  file_put_contents, glob, fnmatch, finfo, stream_socket_*, socket_*, idn_*,
  openssl_pkcs7_*, iconv_mime_decode, ob_start, DatePeriod, libxml options,
  and others). Their flags can be combined, or combining them is only
  redundant, not contradictory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@staabm
staabm force-pushed the create-pull-request/patch-8d54l49 branch from 42f523c to ca0457f Compare September 24, 2026 08:21
@staabm
staabm merged commit b0b0f75 into phpstan:2.3.x Sep 24, 2026
854 of 876 checks passed
@staabm
staabm deleted the create-pull-request/patch-8d54l49 branch September 24, 2026 08:43
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.

verify mutually exclusive bitmask parameters

3 participants