13
13
use Psalm \Internal \Codebase \TaintFlowGraph ;
14
14
use Psalm \Internal \DataFlow \DataFlowNode ;
15
15
use Psalm \Internal \DataFlow \TaintSource ;
16
+ use Psalm \Internal \Type \TypeCombiner ;
16
17
use Psalm \Issue \ImpureVariable ;
17
18
use Psalm \Issue \InvalidScope ;
18
19
use Psalm \Issue \PossiblyUndefinedGlobalVariable ;
22
23
use Psalm \IssueBuffer ;
23
24
use Psalm \Type ;
24
25
use Psalm \Type \Atomic \TArray ;
26
+ use Psalm \Type \Atomic \TBool ;
25
27
use Psalm \Type \Atomic \TInt ;
26
28
use Psalm \Type \Atomic \TIntRange ;
27
29
use Psalm \Type \Atomic \TKeyedArray ;
@@ -645,6 +647,9 @@ public static function getGlobalType(string $var_id, int $codebase_analysis_php_
645
647
$ request_time_float_helper = Type::getFloat ();
646
648
$ request_time_float_helper ->possibly_undefined = true ;
647
649
650
+ $ bool_string_helper = new Union ([new TBool (), new TString ()]);
651
+ $ bool_string_helper ->possibly_undefined = true ;
652
+
648
653
$ detailed_type = new TKeyedArray ([
649
654
// https://www.php.net/manual/en/reserved.variables.server.php
650
655
'PHP_SELF ' => $ non_empty_string_helper ,
@@ -719,6 +724,9 @@ public static function getGlobalType(string $var_id, int $codebase_analysis_php_
719
724
'HTTP_SEC_CH_UA_PLATFORM ' => $ non_empty_string_helper ,
720
725
'HTTP_SEC_CH_UA_MOBILE ' => $ non_empty_string_helper ,
721
726
'HTTP_SEC_CH_UA ' => $ non_empty_string_helper ,
727
+ // phpunit
728
+ 'APP_DEBUG ' => $ bool_string_helper ,
729
+ 'APP_ENV ' => $ string_helper ,
722
730
]);
723
731
724
732
// generic case for all other elements
@@ -739,15 +747,15 @@ public static function getGlobalType(string $var_id, int $codebase_analysis_php_
739
747
new TNonEmptyList (Type::getString ()),
740
748
]),
741
749
'size ' => new Union ([
742
- new TInt ( ),
750
+ new TIntRange ( 0 , null ),
743
751
new TNonEmptyList (Type::getInt ()),
744
752
]),
745
753
'tmp_name ' => new Union ([
746
754
new TString (),
747
755
new TNonEmptyList (Type::getString ()),
748
756
]),
749
757
'error ' => new Union ([
750
- new TInt ( ),
758
+ new TIntRange ( 0 , 8 ),
751
759
new TNonEmptyList (Type::getInt ()),
752
760
]),
753
761
];
@@ -761,7 +769,14 @@ public static function getGlobalType(string $var_id, int $codebase_analysis_php_
761
769
762
770
$ type = new TKeyedArray ($ values );
763
771
764
- return new Union ([$ type ]);
772
+ // $_FILES['userfile']['...'] case
773
+ $ named_type = new TArray ([Type::getNonEmptyString (), new Union ([$ type ])]);
774
+
775
+ // by default $_FILES is an empty array
776
+ $ default_type = new TArray ([Type::getNever (), Type::getNever ()]);
777
+
778
+ // ideally we would have 4 separate arrays with distinct types, but that isn't possible with psalm atm
779
+ return TypeCombiner::combine ([$ default_type , $ type , $ named_type ]);
765
780
}
766
781
767
782
if ($ var_id === '$_SESSION ' ) {
0 commit comments