diff --git a/conf/config.neon b/conf/config.neon index 19b6388858..0f4a3e959e 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -1569,6 +1569,11 @@ services: tags: - phpstan.dynamicFunctionThrowTypeExtension + - + class: PHPStan\Type\Php\OpenSslEncryptParameterOutTypeExtension + tags: + - phpstan.functionParameterOutTypeExtension + - class: PHPStan\Type\Php\ParseStrParameterOutTypeExtension tags: diff --git a/src/Type/Php/OpenSslEncryptParameterOutTypeExtension.php b/src/Type/Php/OpenSslEncryptParameterOutTypeExtension.php new file mode 100644 index 0000000000..1877a4377f --- /dev/null +++ b/src/Type/Php/OpenSslEncryptParameterOutTypeExtension.php @@ -0,0 +1,57 @@ +getName() === 'openssl_encrypt' && $parameter->getName() === 'tag'; + } + + public function getParameterOutTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $funcCall, ParameterReflection $parameter, Scope $scope): ?Type + { + $args = $funcCall->getArgs(); + $cipherArg = $args[1] ?? null; + + if ($cipherArg === null) { + return null; + } + + $cipherType = current($scope->getType($cipherArg->value)->getConstantStrings()); + + if ($cipherType === false) { + return TypeCombinator::addNull(new StringType()); + } + + $cipher = strtolower($cipherType->getValue()); + $mode = substr($cipher, -3); + + if (!in_array($mode, openssl_get_cipher_methods(), true)) { + return new NullType(); + } + + if (in_array($mode, ['gcm', 'ccm'], true)) { + return new StringType(); + } + + return new NullType(); + } + +} diff --git a/tests/PHPStan/Analyser/nsrt/openssl-encrypt.php b/tests/PHPStan/Analyser/nsrt/openssl-encrypt.php new file mode 100644 index 0000000000..85430697a2 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/openssl-encrypt.php @@ -0,0 +1,46 @@ +