Skip to content

Commit e22aae5

Browse files
committed
Implement OpenSslEncryptParameterOutTypeExtension
1 parent b5fc9ec commit e22aae5

File tree

3 files changed

+108
-0
lines changed

3 files changed

+108
-0
lines changed

conf/config.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1569,6 +1569,11 @@ services:
15691569
tags:
15701570
- phpstan.dynamicFunctionThrowTypeExtension
15711571

1572+
-
1573+
class: PHPStan\Type\Php\OpenSslEncryptParameterOutTypeExtension
1574+
tags:
1575+
- phpstan.functionParameterOutTypeExtension
1576+
15721577
-
15731578
class: PHPStan\Type\Php\ParseStrParameterOutTypeExtension
15741579
tags:
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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\Reflection\FunctionReflection;
8+
use PHPStan\Reflection\ParameterReflection;
9+
use PHPStan\Type\FunctionParameterOutTypeExtension;
10+
use PHPStan\Type\NullType;
11+
use PHPStan\Type\StringType;
12+
use PHPStan\Type\Type;
13+
use PHPStan\Type\TypeCombinator;
14+
use function current;
15+
use function in_array;
16+
use function openssl_get_cipher_methods;
17+
use function strtolower;
18+
use function substr;
19+
20+
final class OpenSslEncryptParameterOutTypeExtension implements FunctionParameterOutTypeExtension
21+
{
22+
23+
public function isFunctionSupported(FunctionReflection $functionReflection, ParameterReflection $parameter): bool
24+
{
25+
return $functionReflection->getName() === 'openssl_encrypt' && $parameter->getName() === 'tag';
26+
}
27+
28+
public function getParameterOutTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $funcCall, ParameterReflection $parameter, Scope $scope): ?Type
29+
{
30+
$args = $funcCall->getArgs();
31+
$cipherArg = $args[1] ?? null;
32+
33+
if ($cipherArg === null) {
34+
return null;
35+
}
36+
37+
$cipherType = current($scope->getType($cipherArg->value)->getConstantStrings());
38+
39+
if ($cipherType === false) {
40+
return TypeCombinator::addNull(new StringType());
41+
}
42+
43+
$cipher = strtolower($cipherType->getValue());
44+
$mode = substr($cipher, -3);
45+
46+
if (!in_array($mode, openssl_get_cipher_methods(), true)) {
47+
return new NullType();
48+
}
49+
50+
if (in_array($mode, ['gcm', 'ccm'], true)) {
51+
return new StringType();
52+
}
53+
54+
return new NullType();
55+
}
56+
57+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace OpenSslEncrypt;
6+
7+
use function PHPStan\Testing\assertType;
8+
9+
class Foo
10+
{
11+
public function testStringCipher(string $cipher): void
12+
{
13+
openssl_encrypt('data', $cipher, random_bytes(32), OPENSSL_RAW_DATA, random_bytes(16), $tag);
14+
assertType('string|null', $tag);
15+
}
16+
17+
public function testUnknownCipher(): void
18+
{
19+
openssl_encrypt('data', 'aes-256-cde', random_bytes(32), OPENSSL_RAW_DATA, random_bytes(16), $tag);
20+
assertType('null', $tag);
21+
22+
openssl_encrypt('data', 'abc-256-gcm', random_bytes(32), OPENSSL_RAW_DATA, random_bytes(16), $tag);
23+
assertType('null', $tag);
24+
25+
openssl_encrypt('data', 'abc-256-ccm', random_bytes(32), OPENSSL_RAW_DATA, random_bytes(16), $tag);
26+
assertType('null', $tag);
27+
}
28+
29+
public function testAeadCipher(): void
30+
{
31+
$cipher = 'aes-256-gcm';
32+
openssl_encrypt('data', $cipher, random_bytes(32), OPENSSL_RAW_DATA, random_bytes(16), $tag);
33+
assertType('string', $tag);
34+
35+
$cipher = 'aes-256-ccm';
36+
openssl_encrypt('data', $cipher, random_bytes(32), OPENSSL_RAW_DATA, random_bytes(16), $tag);
37+
assertType('string', $tag);
38+
}
39+
40+
public function testNonAeadCipher(): void
41+
{
42+
$cipher = 'aes-256-cbc';
43+
openssl_encrypt('data', $cipher, random_bytes(32), OPENSSL_RAW_DATA, random_bytes(16), $tag);
44+
assertType('null', $tag);
45+
}
46+
}

0 commit comments

Comments
 (0)