Skip to content

Commit cdeeff4

Browse files
VincentLangletphpstan-bot
authored andcommitted
Fix SimplXmlElement and GMP casts (phpstan#5020)
1 parent d7b5f35 commit cdeeff4

File tree

7 files changed

+138
-16
lines changed

7 files changed

+138
-16
lines changed

resources/functionMap.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,7 +1650,7 @@
16501650
'DomXsltStylesheet::result_dump_mem' => ['string', 'xmldoc'=>'DOMDocument'],
16511651
'DOTNET::__construct' => ['void', 'assembly_name'=>'string', 'class_name'=>'string', 'codepage='=>'int'],
16521652
'dotnet_load' => ['int', 'assembly_name'=>'string', 'datatype_name='=>'string', 'codepage='=>'int'],
1653-
'doubleval' => ['float', 'var'=>'int|float|__stringNotStringable|bool|array|resource|null'],
1653+
'doubleval' => ['float', 'var'=>'int|float|__stringNotStringable|bool|array|resource|GMP|SimpleXMLElement|null'],
16541654
'Ds\Deque::__construct' => ['void', 'values='=>'mixed'],
16551655
'Ds\Deque::count' => ['0|positive-int'],
16561656
'Ds\Deque::jsonSerialize' => ['array'],
@@ -2448,7 +2448,7 @@
24482448
'finfo_file' => ['string|false', 'finfo'=>'resource', 'file_name'=>'string', 'options='=>'int', 'context='=>'resource'],
24492449
'finfo_open' => ['resource|false', 'options='=>'int', 'arg='=>'string'],
24502450
'finfo_set_flags' => ['bool', 'finfo'=>'resource', 'options'=>'int'],
2451-
'floatval' => ['float', 'var'=>'int|float|__stringNotStringable|bool|array|resource|null'],
2451+
'floatval' => ['float', 'var'=>'int|float|__stringNotStringable|bool|array|resource|GMP|SimpleXMLElement|null'],
24522452
'flock' => ['bool', 'fp'=>'resource', 'operation'=>'int-mask<LOCK_SH, LOCK_EX, LOCK_UN, LOCK_NB>', '&w_wouldblock='=>'0|1'],
24532453
'floor' => ['__benevolent<float|false>', 'number'=>'float'],
24542454
'flush' => ['void'],
@@ -5075,7 +5075,7 @@
50755075
'intltz_to_date_time_zone' => ['DateTimeZone|false', 'obj'=>''],
50765076
'intltz_use_daylight_time' => ['bool', 'obj'=>''],
50775077
'intlz_create_default' => ['IntlTimeZone'],
5078-
'intval' => ['int', 'var'=>'int|float|__stringNotStringable|bool|array|resource|null', 'base='=>'int'],
5078+
'intval' => ['int', 'var'=>'int|float|__stringNotStringable|bool|array|resource|GMP|SimpleXMLElement|null', 'base='=>'int'],
50795079
'InvalidArgumentException::__clone' => ['void'],
50805080
'InvalidArgumentException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?InvalidArgumentException)'],
50815081
'InvalidArgumentException::__toString' => ['string'],
@@ -10438,7 +10438,7 @@
1043810438
'strtoupper' => ['uppercase-string', 'str'=>'string'],
1043910439
'strtr' => ['string', 'str'=>'string', 'from'=>'string', 'to'=>'string'],
1044010440
'strtr\'1' => ['string', 'str'=>'string', 'replace_pairs'=>'array'],
10441-
'strval' => ['string', 'var'=>'__stringAndStringable|int|float|bool|resource|null'],
10441+
'strval' => ['string', 'var'=>'__stringAndStringable|int|float|bool|resource|GMP|null'],
1044210442
'substr' => ['__benevolent<string|false>', 'string'=>'string', 'start'=>'int', 'length='=>'int'],
1044310443
'substr_compare' => ['int<-1, 1>|false', 'main_str'=>'string', 'str'=>'string', 'offset'=>'int', 'length='=>'int', 'case_sensitivity='=>'bool'],
1044410444
'substr_count' => ['0|positive-int', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'length='=>'int'],

src/Type/ObjectType.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,10 @@ public function toAbsoluteNumber(): Type
773773

774774
public function toInteger(): Type
775775
{
776-
if ($this->isInstanceOf('SimpleXMLElement')->yes()) {
776+
if (
777+
$this->isInstanceOf('SimpleXMLElement')->yes()
778+
|| $this->isInstanceOf('GMP')->yes()
779+
) {
777780
return new IntegerType();
778781
}
779782

@@ -786,15 +789,21 @@ public function toInteger(): Type
786789

787790
public function toFloat(): Type
788791
{
789-
if ($this->isInstanceOf('SimpleXMLElement')->yes()) {
792+
if (
793+
$this->isInstanceOf('SimpleXMLElement')->yes()
794+
|| $this->isInstanceOf('GMP')->yes()
795+
) {
790796
return new FloatType();
791797
}
792798
return new ErrorType();
793799
}
794800

795801
public function toString(): Type
796802
{
797-
if ($this->isInstanceOf('BcMath\Number')->yes()) {
803+
if (
804+
$this->isInstanceOf('BcMath\Number')->yes()
805+
|| $this->isInstanceOf('GMP')->yes()
806+
) {
798807
return new IntersectionType([
799808
new StringType(),
800809
new AccessoryNumericStringType(),
@@ -911,6 +920,7 @@ public function toBoolean(): BooleanType
911920
if (
912921
$this->isInstanceOf('SimpleXMLElement')->yes()
913922
|| $this->isInstanceOf('BcMath\Number')->yes()
923+
|| $this->isInstanceOf('GMP')->yes()
914924
) {
915925
return new BooleanType();
916926
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace Bug14136Nsrt;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
$xml = <<<'EOT'
8+
<?xml version="1.0"?><item>3</item>
9+
EOT;
10+
11+
$xml = simplexml_load_string($xml);
12+
assertType('int', intval($xml));
13+
assertType('int', intval(gmp_init(42)));
14+
assertType('int', (int) ($xml));
15+
assertType('int', (int) (gmp_init(42)));
16+
17+
assertType('float', floatval($xml));
18+
assertType('float', floatval(gmp_init(42)));
19+
assertType('float', (float) ($xml));
20+
assertType('float', (float) (gmp_init(42)));
21+
22+
assertType('string', strval($xml));
23+
assertType('non-empty-string&numeric-string', strval(gmp_init(42)));
24+
assertType('string', (string) ($xml));
25+
assertType('non-empty-string&numeric-string', (string) (gmp_init(42)));
26+
27+
assertType('bool', boolval($xml));
28+
assertType('bool', boolval(gmp_init(0)));
29+
assertType('bool', (bool) ($xml));
30+
assertType('bool', (bool) (gmp_init(0)));

tests/PHPStan/Rules/Cast/InvalidCastRuleTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ public function testRuleWithNullsafeVariant(): void
7272
]);
7373
}
7474

75+
public function testBug14136(): void
76+
{
77+
$this->analyse([__DIR__ . '/data/bug-14136.php'], []);
78+
}
79+
7580
public function testCastObjectToString(): void
7681
{
7782
$this->analyse([__DIR__ . '/data/cast-object-to-string.php'], [
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug14136Cast;
4+
5+
$xml = <<<'EOT'
6+
<?xml version="1.0"?><item>3</item>
7+
EOT;
8+
9+
$xml = simplexml_load_string($xml);
10+
var_dump(intval($xml));
11+
var_dump(intval(gmp_init(42)));
12+
var_dump((int) ($xml));
13+
var_dump((int)(gmp_init(42)));
14+
15+
var_dump(floatval ($xml));
16+
var_dump(floatval(gmp_init(42)));
17+
var_dump((float) ($xml));
18+
var_dump((float)(gmp_init(42)));
19+
20+
var_dump(strval($xml));
21+
var_dump(strval(gmp_init(42)));
22+
var_dump((string) ($xml));
23+
var_dump((string)(gmp_init(42)));
24+
25+
var_dump(boolval($xml));
26+
var_dump(boolval(gmp_init(42)));
27+
var_dump((bool) ($xml));
28+
var_dump((bool) (gmp_init(42)));
29+
30+
// Union
31+
intval(rand(0,1) ? gmp_init(42) : 'abc');
32+
intval(rand(0,1) ? gmp_init(42) : []);
33+
intval(rand(0,1) ? gmp_init(42) : '123');
34+
(int) (rand(0,1) ? gmp_init(42) : 'abc');
35+
(int) (rand(0,1) ? gmp_init(42) : []);
36+
(int) (rand(0,1) ? gmp_init(42) : '123');

tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2481,39 +2481,39 @@ public function testBug6560(string $fileName): void
24812481

24822482
$this->analyse([__DIR__ . '/data/' . $fileName], [
24832483
[
2484-
sprintf('Parameter #1 %s of function strval expects bool|float|int|resource|string|null, array given.', $varName),
2484+
sprintf('Parameter #1 %s of function strval expects bool|float|GMP|int|resource|string|null, array given.', $varName),
24852485
23,
24862486
],
24872487
[
2488-
sprintf('Parameter #1 %s of function strval expects bool|float|int|resource|string|null, stdClass given.', $varName),
2488+
sprintf('Parameter #1 %s of function strval expects bool|float|GMP|int|resource|string|null, stdClass given.', $varName),
24892489
77,
24902490
],
24912491
[
2492-
sprintf('Parameter #1 %s of function intval expects array|bool|float|int|resource|string|null, stdClass given.', $varName),
2492+
sprintf('Parameter #1 %s of function intval expects array|bool|float|GMP|int|resource|SimpleXMLElement|string|null, stdClass given.', $varName),
24932493
80,
24942494
],
24952495
[
2496-
sprintf('Parameter #1 %s of function floatval expects array|bool|float|int|resource|string|null, stdClass given.', $varName),
2496+
sprintf('Parameter #1 %s of function floatval expects array|bool|float|GMP|int|resource|SimpleXMLElement|string|null, stdClass given.', $varName),
24972497
83,
24982498
],
24992499
[
2500-
sprintf('Parameter #1 %s of function intval expects array|bool|float|int|resource|string|null, %s@anonymous/tests/PHPStan/Rules/Functions/data/' . $fileName . ':13 given.', $varName, $stringableName),
2500+
sprintf('Parameter #1 %s of function intval expects array|bool|float|GMP|int|resource|SimpleXMLElement|string|null, %s@anonymous/tests/PHPStan/Rules/Functions/data/' . $fileName . ':13 given.', $varName, $stringableName),
25012501
89,
25022502
],
25032503
[
2504-
sprintf('Parameter #1 %s of function floatval expects array|bool|float|int|resource|string|null, %s@anonymous/tests/PHPStan/Rules/Functions/data/' . $fileName . ':13 given.', $varName, $stringableName),
2504+
sprintf('Parameter #1 %s of function floatval expects array|bool|float|GMP|int|resource|SimpleXMLElement|string|null, %s@anonymous/tests/PHPStan/Rules/Functions/data/' . $fileName . ':13 given.', $varName, $stringableName),
25052505
92,
25062506
],
25072507
[
2508-
sprintf('Parameter #1 %s of function strval expects bool|float|int|resource|string|null, mixed given.', $varName),
2508+
sprintf('Parameter #1 %s of function strval expects bool|float|GMP|int|resource|string|null, mixed given.', $varName),
25092509
95,
25102510
],
25112511
[
2512-
sprintf('Parameter #1 %s of function intval expects array|bool|float|int|resource|string|null, mixed given.', $varName),
2512+
sprintf('Parameter #1 %s of function intval expects array|bool|float|GMP|int|resource|SimpleXMLElement|string|null, mixed given.', $varName),
25132513
98,
25142514
],
25152515
[
2516-
sprintf('Parameter #1 %s of function floatval expects array|bool|float|int|resource|string|null, mixed given.', $varName),
2516+
sprintf('Parameter #1 %s of function floatval expects array|bool|float|GMP|int|resource|SimpleXMLElement|string|null, mixed given.', $varName),
25172517
101,
25182518
],
25192519
]);
@@ -2678,6 +2678,11 @@ public function testBug9652(): void
26782678
$this->analyse([__DIR__ . '/data/bug-9652.php'], []);
26792679
}
26802680

2681+
public function testBug14136(): void
2682+
{
2683+
$this->analyse([__DIR__ . '/data/bug-14136.php'], []);
2684+
}
2685+
26812686
#[RequiresPhp('>= 8.1')]
26822687
public function testBug8936(): void
26832688
{
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug14136;
4+
5+
$xml = <<<'EOT'
6+
<?xml version="1.0"?><item>3</item>
7+
EOT;
8+
9+
$xml = simplexml_load_string($xml);
10+
var_dump(intval($xml));
11+
var_dump(intval(gmp_init(42)));
12+
var_dump((int) ($xml));
13+
var_dump((int)(gmp_init(42)));
14+
15+
var_dump(floatval ($xml));
16+
var_dump(floatval(gmp_init(42)));
17+
var_dump((float) ($xml));
18+
var_dump((float)(gmp_init(42)));
19+
20+
var_dump(strval($xml));
21+
var_dump(strval(gmp_init(42)));
22+
var_dump((string) ($xml));
23+
var_dump((string)(gmp_init(42)));
24+
25+
var_dump(boolval($xml));
26+
var_dump(boolval(gmp_init(42)));
27+
var_dump((bool) ($xml));
28+
var_dump((bool) (gmp_init(42)));
29+
30+
// Union
31+
intval(rand(0,1) ? gmp_init(42) : 'abc');
32+
intval(rand(0,1) ? gmp_init(42) : []);
33+
intval(rand(0,1) ? gmp_init(42) : '123');
34+
(int) (rand(0,1) ? gmp_init(42) : 'abc');
35+
(int) (rand(0,1) ? gmp_init(42) : []);
36+
(int) (rand(0,1) ? gmp_init(42) : '123');

0 commit comments

Comments
 (0)