Skip to content

Filter unsupported OpenSSL cipher methods on PHP 8.0-8.4#4982

Merged
VincentLanglet merged 3 commits intophpstan:2.1.xfrom
VincentLanglet:fix/13692
Feb 18, 2026
Merged

Filter unsupported OpenSSL cipher methods on PHP 8.0-8.4#4982
VincentLanglet merged 3 commits intophpstan:2.1.xfrom
VincentLanglet:fix/13692

Conversation

@VincentLanglet
Copy link
Contributor

Summary

On PHP 8.0-8.4, openssl_get_cipher_methods() reports cipher algorithms that are not actually supported by OpenSSL functions like openssl_cipher_iv_length() and openssl_cipher_key_length(). This is due to a PHP bug (php/php-src#19994) where openssl_get_cipher_methods() uses a different source of algorithms than the actual cipher functions, causing it to list algorithms that OpenSSL 3.0 has disabled by default.

This caused PHPStan to incorrectly refine the return type of these functions — for example, openssl_cipher_iv_length('aes-128-cbc-cts') was narrowed to int when it actually returns false on PHP 8.0-8.4.

Changes

  • Added src/Type/Php/OpenSslCipherMethodsProvider.php — a shared service that filters the cipher methods list by actually testing each algorithm with openssl_cipher_iv_length(), excluding those that return false (i.e. are not truly supported)
  • Updated src/Type/Php/OpensslCipherFunctionsReturnTypeExtension.php to use the new shared provider instead of directly querying openssl_get_cipher_methods()
  • Updated src/Type/Php/OpenSslEncryptParameterOutTypeExtension.php to use the same shared provider for consistent behavior

Root cause

openssl_get_cipher_methods() on PHP 8.0-8.4 uses EVP_CIPHER_do_all_sorted() to enumerate algorithms, while functions like openssl_cipher_iv_length() use EVP_get_cipherbyname() to resolve them. With OpenSSL 3.0+, the former returns algorithms from all providers (including disabled ones), while the latter only returns algorithms from loaded providers. This discrepancy was fixed in PHP 8.5 via a refactoring of the OpenSSL implementation.

The fix filters the algorithm list at PHPStan's analysis time by calling openssl_cipher_iv_length() for each algorithm and removing those that fail, ensuring only truly supported algorithms are used for type refinement.

Test

Added tests/PHPStan/Analyser/nsrt/bug-13692.php — verifies that openssl_cipher_iv_length('aes-128-cbc-cts') is correctly refined to false (not int) on PHP 8.4, while aes-128-cbc still correctly refines to int.

Fixes phpstan/phpstan#13692

phpstan-bot and others added 2 commits February 17, 2026 23:18
- openssl_get_cipher_methods() reports algorithms not actually supported
  on PHP 8.0-8.4 due to php/php-src#19994, causing incorrect type
  refinement (e.g. aes-128-cbc-cts narrowed to int instead of false)
- Added OpenSslCipherMethodsProvider that filters cipher methods by
  testing each with openssl_cipher_iv_length() to exclude broken ones
- Updated OpensslCipherFunctionsReturnTypeExtension and
  OpenSslEncryptParameterOutTypeExtension to use the shared provider
- New regression test in tests/PHPStan/Analyser/nsrt/bug-13692.php

Closes phpstan/phpstan#13692
@phpstan-bot
Copy link
Collaborator

You've opened the pull request against the latest branch 2.2.x. PHPStan 2.2 is not going to be released for months. If your code is relevant on 2.1.x and you want it to be released sooner, please rebase your pull request and change its target to 2.1.x.

Comment on lines +42 to +44
if (PHP_VERSION_ID >= 80000 && PHP_VERSION_ID < 80500) {
yield __DIR__ . '/data/bug-13692.php';
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need separate assertions for this test for other php versions?

@VincentLanglet VincentLanglet merged commit ff3110d into phpstan:2.1.x Feb 18, 2026
640 of 645 checks passed
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.

Openssl cipher method refinement is unsafe on PHP 8.4 and older due to a PHP bug

3 participants