Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 163d178

Browse files
stofondrejmirtes
authored andcommitted
Add more precise return types for the openssl cipher functions
1 parent 5c3eed5 commit 163d178

File tree

4 files changed

+161
-0
lines changed

4 files changed

+161
-0
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Type\Php;
4+
5+
use PhpParser\Node\Expr\FuncCall;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Php\PhpVersion;
8+
use PHPStan\Reflection\FunctionReflection;
9+
use PHPStan\Reflection\ParametersAcceptorSelector;
10+
use PHPStan\Type\Constant\ConstantBooleanType;
11+
use PHPStan\Type\Constant\ConstantStringType;
12+
use PHPStan\Type\DynamicFunctionReturnTypeExtension;
13+
use PHPStan\Type\Type;
14+
use PHPStan\Type\TypeCombinator;
15+
use function array_map;
16+
use function array_unique;
17+
use function count;
18+
use function function_exists;
19+
use function in_array;
20+
use function is_null;
21+
use function openssl_get_cipher_methods;
22+
use function strtoupper;
23+
24+
#[AutowiredService]
25+
final class OpensslCipherFunctionsReturnTypeExtension implements DynamicFunctionReturnTypeExtension
26+
{
27+
28+
/** @var string[]|null */
29+
private ?array $supportedAlgorithms = null;
30+
31+
public function __construct(private PhpVersion $phpVersion)
32+
{
33+
}
34+
35+
public function isFunctionSupported(FunctionReflection $functionReflection): bool
36+
{
37+
return in_array($functionReflection->getName(), ['openssl_cipher_iv_length', 'openssl_cipher_key_length'], true);
38+
}
39+
40+
public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type
41+
{
42+
if (!$this->phpVersion->throwsValueErrorForInternalFunctions()) {
43+
return null;
44+
}
45+
46+
if (count($functionCall->getArgs()) < 1) {
47+
return null;
48+
}
49+
50+
$strings = $scope->getType($functionCall->getArgs()[0]->value)->getConstantStrings();
51+
$results = array_unique(array_map(fn (ConstantStringType $algorithm): bool => $this->isSupportedAlgorithm($algorithm->getValue()), $strings));
52+
53+
if (count($results) !== 1) {
54+
return null;
55+
}
56+
57+
$returnType = ParametersAcceptorSelector::selectFromArgs(
58+
$scope,
59+
$functionCall->getArgs(),
60+
$functionReflection->getVariants(),
61+
)->getReturnType();
62+
63+
return $results[0]
64+
? TypeCombinator::remove($returnType, new ConstantBooleanType(false))
65+
: new ConstantBooleanType(false);
66+
}
67+
68+
private function isSupportedAlgorithm(string $algorithm): bool
69+
{
70+
return in_array(strtoupper($algorithm), $this->getSupportedAlgorithms(), true);
71+
}
72+
73+
/** @return string[] */
74+
private function getSupportedAlgorithms(): array
75+
{
76+
if (!is_null($this->supportedAlgorithms)) {
77+
return $this->supportedAlgorithms;
78+
}
79+
80+
$supportedAlgorithms = [];
81+
if (function_exists('openssl_get_cipher_methods')) {
82+
$supportedAlgorithms = openssl_get_cipher_methods(true);
83+
}
84+
$this->supportedAlgorithms = array_map('strtoupper', $supportedAlgorithms);
85+
86+
return $this->supportedAlgorithms;
87+
}
88+
89+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php // lint < 8.0
2+
3+
namespace OpensslCipherIvLengthPhp7;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class OpensslCipher
8+
{
9+
10+
/**
11+
* @param 'aes-256-cbc'|'aes128'|'aes-128-cbc' $validAlgorithms
12+
* @param 'aes-256-cbc'|'invalid' $validAndInvalidAlgorithms
13+
*/
14+
public function doFoo(string $s, $validAlgorithms, $validAndInvalidAlgorithms)
15+
{
16+
assertType('int|false', openssl_cipher_iv_length('aes-256-cbc'));
17+
assertType('int|false', openssl_cipher_iv_length('AES-256-CBC'));
18+
assertType('int|false', openssl_cipher_iv_length('unsupported'));
19+
assertType('int|false', openssl_cipher_iv_length($s));
20+
assertType('int|false', openssl_cipher_iv_length($validAlgorithms));
21+
assertType('int|false', openssl_cipher_iv_length($validAndInvalidAlgorithms));
22+
}
23+
24+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php // lint >= 8.0
2+
3+
namespace OpensslCipherIvLengthPhp8;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class OpensslCipher
8+
{
9+
10+
/**
11+
* @param 'aes-256-cbc'|'aes128'|'aes-128-cbc' $validAlgorithms
12+
* @param 'aes-256-cbc'|'invalid' $validAndInvalidAlgorithms
13+
*/
14+
public function doFoo(string $s, $validAlgorithms, $validAndInvalidAlgorithms)
15+
{
16+
assertType('int', openssl_cipher_iv_length('aes-256-cbc'));
17+
assertType('int', openssl_cipher_iv_length('AES-256-CBC'));
18+
assertType('false', openssl_cipher_iv_length('unsupported'));
19+
assertType('int|false', openssl_cipher_iv_length($s));
20+
assertType('int', openssl_cipher_iv_length($validAlgorithms));
21+
assertType('int|false', openssl_cipher_iv_length($validAndInvalidAlgorithms));
22+
}
23+
24+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php // lint >= 8.2
2+
3+
namespace OpensslCipherKeyLength;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class OpensslCipher
8+
{
9+
10+
/**
11+
* @param 'aes-256-cbc'|'aes128'|'aes-128-cbc' $validAlgorithms
12+
* @param 'aes-256-cbc'|'invalid' $validAndInvalidAlgorithms
13+
*/
14+
public function doFoo(string $s, $validAlgorithms, $validAndInvalidAlgorithms)
15+
{
16+
assertType('int', openssl_cipher_key_length('aes-256-cbc'));
17+
assertType('int', openssl_cipher_key_length('AES-256-CBC'));
18+
assertType('false', openssl_cipher_key_length('unsupported'));
19+
assertType('int|false', openssl_cipher_key_length($s));
20+
assertType('int', openssl_cipher_key_length($validAlgorithms));
21+
assertType('int|false', openssl_cipher_key_length($validAndInvalidAlgorithms));
22+
}
23+
24+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /