Skip to content

Commit 5edaeaf

Browse files
Rework
1 parent 86a908c commit 5edaeaf

File tree

5 files changed

+48
-18
lines changed

5 files changed

+48
-18
lines changed

resources/functionMap.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3909,16 +3909,16 @@
39093909
'HaruPage::stroke' => ['bool', 'close_path='=>'bool'],
39103910
'HaruPage::textOut' => ['bool', 'x'=>'float', 'y'=>'float', 'text'=>'string'],
39113911
'HaruPage::textRect' => ['bool', 'left'=>'float', 'top'=>'float', 'right'=>'float', 'bottom'=>'float', 'text'=>'string', 'align='=>'int'],
3912-
'hash' => ['(non-falsy-string&lowercase-string)|false', 'algo'=>'string', 'data'=>'string', 'raw_output='=>'bool'],
3912+
'hash' => ['non-falsy-string|false', 'algo'=>'string', 'data'=>'string', 'raw_output='=>'bool'],
39133913
'hash_algos' => ['non-empty-list<non-falsy-string>'],
39143914
'hash_copy' => ['HashContext', 'context'=>'HashContext'],
39153915
'hash_equals' => ['bool', 'known_string'=>'string', 'user_string'=>'string'],
3916-
'hash_file' => ['(non-falsy-string&lowercase-string)|false', 'algo'=>'string', 'filename'=>'string', 'raw_output='=>'bool'],
3917-
'hash_final' => ['non-falsy-string&lowercase-string', 'context'=>'HashContext', 'raw_output='=>'bool'],
3918-
'hash_hkdf' => ['(non-falsy-string&lowercase-string)|false', 'algo'=>'string', 'key'=>'string', 'length='=>'int', 'info='=>'string', 'salt='=>'string'],
3919-
'hash_hmac' => ['(non-falsy-string&lowercase-string)|false', 'algo'=>'string', 'data'=>'string', 'key'=>'string', 'raw_output='=>'bool'],
3916+
'hash_file' => ['non-falsy-string|false', 'algo'=>'string', 'filename'=>'string', 'raw_output='=>'bool'],
3917+
'hash_final' => ['non-falsy-string', 'context'=>'HashContext', 'raw_output='=>'bool'],
3918+
'hash_hkdf' => ['non-falsy-string|false', 'algo'=>'string', 'key'=>'string', 'length='=>'int', 'info='=>'string', 'salt='=>'string'],
3919+
'hash_hmac' => ['non-falsy-string|false', 'algo'=>'string', 'data'=>'string', 'key'=>'string', 'raw_output='=>'bool'],
39203920
'hash_hmac_algos' => ['non-empty-list<non-falsy-string>'],
3921-
'hash_hmac_file' => ['(non-falsy-string&lowercase-string)|false', 'algo'=>'string', 'filename'=>'string', 'key'=>'string', 'raw_output='=>'bool'],
3921+
'hash_hmac_file' => ['non-falsy-string|false', 'algo'=>'string', 'filename'=>'string', 'key'=>'string', 'raw_output='=>'bool'],
39223922
'hash_init' => ['HashContext', 'algo'=>'string', 'options='=>'int', 'key='=>'string'],
39233923
'hash_pbkdf2' => ['(non-falsy-string&lowercase-string)|false', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'raw_output='=>'bool'],
39243924
'hash_update' => ['bool', 'context'=>'HashContext', 'data'=>'string'],

resources/functionMap_php80delta.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@
5353
'gmmktime' => ['int|false', 'hour'=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'],
5454
'hash' => ['non-falsy-string', 'algo'=>'string', 'data'=>'string', 'raw_output='=>'bool'],
5555
'hash_hkdf' => ['non-falsy-string', 'algo'=>'string', 'key'=>'string', 'length='=>'int', 'info='=>'string', 'salt='=>'string'],
56-
'hash_hmac' => ['non-empty-string', 'algo'=>'string', 'data'=>'string', 'key'=>'string', 'raw_output='=>'bool'],
57-
'hash_pbkdf2' => ['non-empty-string', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'raw_output='=>'bool'],
56+
'hash_hmac' => ['non-falsy-string', 'algo'=>'string', 'data'=>'string', 'key'=>'string', 'raw_output='=>'bool'],
57+
'hash_pbkdf2' => ['non-falsy-string', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'raw_output='=>'bool'],
5858
'imageaffine' => ['false|object', 'src'=>'resource', 'affine'=>'array', 'clip='=>'array'],
5959
'imagecreate' => ['__benevolent<GdImage|false>', 'width'=>'int', 'height'=>'int'],
6060
'imagecreatefrombmp' => ['false|object', 'filename'=>'string'],
@@ -192,10 +192,10 @@
192192
'gmmktime' => ['int|false', 'hour='=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'],
193193
'gmp_random' => ['GMP', 'limiter='=>'int'],
194194
'gzgetss' => ['string|false', 'zp'=>'resource', 'length'=>'int', 'allowable_tags='=>'string'],
195-
'hash' => ['non-empty-string|false', 'algo'=>'string', 'data'=>'string', 'raw_output='=>'bool'],
196-
'hash_hkdf' => ['non-empty-string|false', 'algo'=>'string', 'key'=>'string', 'length='=>'int', 'info='=>'string', 'salt='=>'string'],
197-
'hash_hmac' => ['non-empty-string|false', 'algo'=>'string', 'data'=>'string', 'key'=>'string', 'raw_output='=>'bool'],
198-
'hash_pbkdf2' => ['non-empty-string|false', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'raw_output='=>'bool'],
195+
'hash' => ['non-falsy-string|false', 'algo'=>'string', 'data'=>'string', 'raw_output='=>'bool'],
196+
'hash_hkdf' => ['non-falsy-string|false', 'algo'=>'string', 'key'=>'string', 'length='=>'int', 'info='=>'string', 'salt='=>'string'],
197+
'hash_hmac' => ['non-falsy-string|false', 'algo'=>'string', 'data'=>'string', 'key'=>'string', 'raw_output='=>'bool'],
198+
'hash_pbkdf2' => ['non-falsy-string|false', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'raw_output='=>'bool'],
199199
'hebrevc' => ['string', 'str'=>'string', 'max_chars_per_line='=>'int'],
200200
'image2wbmp' => ['bool', 'im'=>'resource', 'filename='=>'?string', 'threshold='=>'int'],
201201
'imageaffine' => ['resource|false', 'src'=>'resource', 'affine'=>'array', 'clip='=>'array'],

src/Type/Php/HashFunctionsReturnTypeExtension.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,32 @@ final class HashFunctionsReturnTypeExtension implements DynamicFunctionReturnTyp
3131
'hash' => [
3232
'cryptographic' => false,
3333
'possiblyFalse' => false,
34+
'binary' => 2,
3435
],
3536
'hash_file' => [
3637
'cryptographic' => false,
3738
'possiblyFalse' => true,
39+
'binary' => 2,
3840
],
3941
'hash_hkdf' => [
4042
'cryptographic' => true,
4143
'possiblyFalse' => false,
44+
'binary' => true,
4245
],
4346
'hash_hmac' => [
4447
'cryptographic' => true,
4548
'possiblyFalse' => false,
49+
'binary' => 3,
4650
],
4751
'hash_hmac_file' => [
4852
'cryptographic' => true,
4953
'possiblyFalse' => true,
54+
'binary' => 3,
5055
],
5156
'hash_pbkdf2' => [
5257
'cryptographic' => true,
5358
'possiblyFalse' => false,
59+
'binary' => 5,
5460
],
5561
];
5662

@@ -117,20 +123,32 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
117123
new AccessoryNonFalsyStringType(),
118124
new AccessoryLowercaseStringType(),
119125
]);
126+
$nonFalsyString = new IntersectionType([
127+
new StringType(),
128+
new AccessoryNonFalsyStringType(),
129+
]);
120130

121131
$invalidAlgorithmType = $this->phpVersion->throwsValueErrorForInternalFunctions() ? $neverType : $falseType;
122132
$functionData = self::SUPPORTED_FUNCTIONS[strtolower($functionReflection->getName())];
123133

134+
if (\is_bool($functionData['binary'])) {
135+
$binaryType = new ConstantBooleanType(\is_bool($functionData['binary']));
136+
} elseif (isset($functionCall->getArgs()[$functionData['binary']])) {
137+
$binaryType = $scope->getType($functionCall->getArgs()[$functionData['binary']]->value);
138+
} else {
139+
$binaryType = new ConstantBooleanType(false);
140+
}
141+
124142
$returnTypes = array_map(
125-
function (ConstantStringType $type) use ($functionData, $nonFalsyLowercaseString, $invalidAlgorithmType) {
143+
function (ConstantStringType $type) use ($functionData, $binaryType, $nonFalsyString, $nonFalsyLowercaseString, $invalidAlgorithmType) {
126144
$algorithm = strtolower($type->getValue());
127145
if (!in_array($algorithm, $this->hashAlgorithms, true)) {
128146
return $invalidAlgorithmType;
129147
}
130148
if ($functionData['cryptographic'] && in_array($algorithm, self::NON_CRYPTOGRAPHIC_ALGORITHMS, true)) {
131149
return $invalidAlgorithmType;
132150
}
133-
return $nonFalsyLowercaseString;
151+
return $binaryType->isFalse()->yes() ? $nonFalsyLowercaseString : $nonFalsyString;
134152
},
135153
$constantAlgorithmTypes,
136154
);

tests/PHPStan/Analyser/nsrt/hash-functions-74.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public function hash_hmac(string $string): void
1212
assertType('false', hash_hmac('crc32', 'data', 'key'));
1313
assertType('false', hash_hmac('invalid', 'data', 'key'));
1414
assertType('((lowercase-string&non-falsy-string)|false)', hash_hmac($string, 'data', 'key'));
15+
assertType('(non-falsy-string|false)', hash_hmac($string, 'data', 'key', true));
1516
}
1617

1718
public function hash_hmac_file(): void
@@ -24,6 +25,7 @@ public function hash(string $string): void
2425
{
2526
assertType('false', hash('invalid', 'data', false));
2627
assertType('((lowercase-string&non-falsy-string)|false)', hash($string, 'data'));
28+
assertType('(non-falsy-string|false)', hash($string, 'data', true));
2729
}
2830

2931
public function hash_file(): void
@@ -35,14 +37,15 @@ public function hash_hkdf(string $string): void
3537
{
3638
assertType('false', hash_hkdf('crc32', 'key'));
3739
assertType('false', hash_hkdf('invalid', 'key'));
38-
assertType('((lowercase-string&non-falsy-string)|false)', hash_hkdf($string, 'key'));
40+
assertType('(non-falsy-string|false)', hash_hkdf($string, 'key'));
3941
}
4042

4143
public function hash_pbkdf2(string $string): void
4244
{
4345
assertType('false', hash_pbkdf2('crc32', 'password', 'salt', 1000));
4446
assertType('false', hash_pbkdf2('invalid', 'password', 'salt', 1000));
4547
assertType('((lowercase-string&non-falsy-string)|false)', hash_pbkdf2($string, 'password', 'salt', 1000));
48+
assertType('(non-falsy-string|false)', hash_pbkdf2($string, 'password', 'salt', 1000, 0, true));
4649
}
4750

4851
public function caseSensitive()

tests/PHPStan/Analyser/nsrt/hash-functions.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,43 +14,51 @@ class HashFunctionTests
1414
public function hash_hmac(): void
1515
{
1616
assertType('lowercase-string&non-falsy-string', hash_hmac('md5', 'data', 'key'));
17+
assertType('non-falsy-string', hash_hmac('md5', 'data', 'key', true));
1718
assertType('lowercase-string&non-falsy-string', hash_hmac('sha256', 'data', 'key'));
19+
assertType('non-falsy-string', hash_hmac('sha256', 'data', 'key', true));
1820
}
1921

2022
public function hash_hmac_file(string $string): void
2123
{
2224
assertType('(lowercase-string&non-falsy-string)|false', hash_hmac_file('md5', 'filename', 'key'));
25+
assertType('non-falsy-string|false', hash_hmac_file('md5', 'filename', 'key', true));
2326
assertType('(lowercase-string&non-falsy-string)|false', hash_hmac_file('sha256', 'filename', 'key'));
27+
assertType('non-falsy-string|false', hash_hmac_file('sha256', 'filename', 'key', true));
2428
assertType('((lowercase-string&non-falsy-string)|false)', hash_hmac_file($string, 'filename', 'key'));
29+
assertType('(non-falsy-string|false)', hash_hmac_file($string, 'filename', 'key', true));
2530
}
2631

2732
public function hash($mixed): void
2833
{
2934
assertType('lowercase-string&non-falsy-string', hash('sha256', 'data', false));
30-
assertType('lowercase-string&non-falsy-string', hash('sha256', 'data', true));
35+
assertType('non-falsy-string', hash('sha256', 'data', true));
3136
assertType('lowercase-string&non-falsy-string', hash('md5', $mixed, false));
3237
}
3338

3439
public function hash_file(): void
3540
{
3641
assertType('(lowercase-string&non-falsy-string)|false', hash_file('sha256', 'filename', false));
37-
assertType('(lowercase-string&non-falsy-string)|false', hash_file('sha256', 'filename', true));
42+
assertType('non-falsy-string|false', hash_file('sha256', 'filename', true));
3843
assertType('(lowercase-string&non-falsy-string)|false', hash_file('crc32', 'filename'));
44+
assertType('non-falsy-string|false', hash_file('crc32', 'filename', true));
3945
}
4046

4147
public function hash_hkdf(): void
4248
{
43-
assertType('lowercase-string&non-falsy-string', hash_hkdf('sha256', 'key'));
49+
assertType('non-falsy-string', hash_hkdf('sha256', 'key'));
4450
}
4551

4652
public function hash_pbkdf2(): void
4753
{
4854
assertType('lowercase-string&non-falsy-string', hash_pbkdf2('sha256', 'password', 'salt', 1000));
55+
assertType('non-falsy-string', hash_pbkdf2('sha256', 'password', 'salt', 1000, 0, true));
4956
}
5057

5158
public function caseSensitive()
5259
{
5360
assertType('lowercase-string&non-falsy-string', hash('SHA256', 'data'));
61+
assertType('non-falsy-string', hash('SHA256', 'data', true));
5462
}
5563

5664
public function constantStrings(int $type)
@@ -70,6 +78,7 @@ public function constantStrings(int $type)
7078
}
7179

7280
assertType('lowercase-string&non-falsy-string', hash_pbkdf2($algorithm, 'password', 'salt', 1000));
81+
assertType('non-falsy-string', hash_pbkdf2($algorithm, 'password', 'salt', 1000, 0, true));
7382
}
7483

7584
}

0 commit comments

Comments
 (0)