From 430dfebade8b9132c6c8650a7b41044f6217c5e6 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Sun, 22 Dec 2024 23:36:05 +0800 Subject: [PATCH] Implement `OpenSslEncryptParameterOutTypeExtension` --- conf/config.neon | 5 ++ ...penSslEncryptParameterOutTypeExtension.php | 79 +++++++++++++++++++ .../PHPStan/Analyser/nsrt/openssl-encrypt.php | 73 +++++++++++++++++ 3 files changed, 157 insertions(+) create mode 100644 src/Type/Php/OpenSslEncryptParameterOutTypeExtension.php create mode 100644 tests/PHPStan/Analyser/nsrt/openssl-encrypt.php 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..bfdfc2b35e --- /dev/null +++ b/src/Type/Php/OpenSslEncryptParameterOutTypeExtension.php @@ -0,0 +1,79 @@ +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 = $scope->getType($cipherArg->value); + + return TypeTraverser::map($cipherType, static function (Type $type, callable $traverse): Type { + if ($type instanceof UnionType) { + return $traverse($type); + } + + $tagTypes = []; + + foreach ($type->getConstantStrings() as $cipherType) { + $cipher = strtolower($cipherType->getValue()); + $mode = substr($cipher, -3); + + if (!in_array($cipher, openssl_get_cipher_methods(), true)) { + $tagTypes[] = new NullType(); + continue; + } + + if (in_array($mode, ['gcm', 'ccm'], true)) { + $tagTypes[] = TypeCombinator::intersect( + new StringType(), + new AccessoryNonEmptyStringType(), + ); + continue; + } + + $tagTypes[] = new NullType(); + } + + if ($tagTypes === []) { + return TypeCombinator::addNull(TypeCombinator::intersect( + new StringType(), + new AccessoryNonEmptyStringType(), + )); + } + + return TypeCombinator::union(...$tagTypes); + }); + } + +} diff --git a/tests/PHPStan/Analyser/nsrt/openssl-encrypt.php b/tests/PHPStan/Analyser/nsrt/openssl-encrypt.php new file mode 100644 index 0000000000..91e178514c --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/openssl-encrypt.php @@ -0,0 +1,73 @@ +