Skip to content

Commit f93d238

Browse files
committed
Fix glob CallMap and stub to prevent crash on alpine (and possibly other systems)
1 parent a0a9c27 commit f93d238

File tree

5 files changed

+77
-29
lines changed

5 files changed

+77
-29
lines changed

dictionaries/CallMap.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3330,7 +3330,7 @@
33303330
'gettimeofday' => ['array<string, int>'],
33313331
'gettimeofday\'1' => ['float', 'as_float='=>'true'],
33323332
'gettype' => ['string', 'value'=>'mixed'],
3333-
'glob' => ['false|list{0?:string, ...<non-empty-string>}', 'pattern'=>'string', 'flags='=>'int-mask<GLOB_MARK, GLOB_NOSORT, GLOB_NOCHECK, GLOB_NOESCAPE, GLOB_BRACE, GLOB_ONLYDIR, GLOB_ERR>'],
3333+
'glob' => ['false|list{0?:string, ...<non-empty-string>}', 'pattern'=>'string', 'flags='=>'int<0, max>'],
33343334
'GlobIterator::__construct' => ['void', 'pattern'=>'string', 'flags='=>'int'],
33353335
'GlobIterator::count' => ['int'],
33363336
'GlobIterator::current' => ['FilesystemIterator|SplFileInfo|string'],

dictionaries/CallMap_historical.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10764,7 +10764,7 @@
1076410764
'gettimeofday' => ['array<string, int>'],
1076510765
'gettimeofday\'1' => ['float', 'as_float='=>'true'],
1076610766
'gettype' => ['string', 'value'=>'mixed'],
10767-
'glob' => ['false|list{0?:string, ...<non-empty-string>}', 'pattern'=>'string', 'flags='=>'int-mask<GLOB_MARK, GLOB_NOSORT, GLOB_NOCHECK, GLOB_NOESCAPE, GLOB_BRACE, GLOB_ONLYDIR, GLOB_ERR>'],
10767+
'glob' => ['false|list{0?:string, ...<non-empty-string>}', 'pattern'=>'string', 'flags='=>'int<0, max>'],
1076810768
'gmdate' => ['string', 'format'=>'string', 'timestamp='=>'int'],
1076910769
'gmmktime' => ['int|false', 'hour='=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'],
1077010770
'gmp_abs' => ['GMP', 'num'=>'GMP|string|int'],

src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,12 @@
3232
use ReflectionClass;
3333
use ReflectionFunction;
3434

35+
use function array_merge;
36+
use function array_values;
3537
use function assert;
3638
use function class_exists;
3739
use function function_exists;
40+
use function get_defined_constants;
3841
use function implode;
3942
use function in_array;
4043
use function interface_exists;
@@ -514,6 +517,19 @@ private static function functionEvaluatesToTrue(
514517
return false;
515518
}
516519

520+
if ($function->name->parts === ['defined']
521+
&& isset($function->getArgs()[0])
522+
&& $function->getArgs()[0]->value instanceof PhpParser\Node\Scalar\String_
523+
) {
524+
$predefined_constants = get_defined_constants(true);
525+
if (isset($predefined_constants['user'])) {
526+
unset($predefined_constants['user']);
527+
}
528+
$predefined_constants = array_merge(...array_values($predefined_constants));
529+
530+
return isset($predefined_constants[$function->getArgs()[0]->value->value]);
531+
}
532+
517533
return null;
518534
}
519535
}

stubs/CoreGenericFunctions.phpstub

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,31 +1717,57 @@ function pg_escape_literal($string1, $string2 = null) {}
17171717
*/
17181718
function pg_escape_string($string1, $string2 = null) {}
17191719

1720-
/**
1721-
* @psalm-template P of string
1722-
* @psalm-template F of int-mask<GLOB_MARK, GLOB_NOSORT, GLOB_NOCHECK, GLOB_NOESCAPE, GLOB_BRACE, GLOB_ONLYDIR, GLOB_ERR>
1723-
* @psalm-param P $pattern
1724-
* @psalm-param F $flags
1725-
* @psalm-return (
1726-
* P is ''
1727-
* ? (F is int-mask<GLOB_MARK, GLOB_NOSORT, GLOB_NOESCAPE, GLOB_BRACE, GLOB_ONLYDIR, GLOB_ERR>
1728-
* ? false|list<never>
1729-
* : (F is int-mask<GLOB_MARK, GLOB_NOSORT, GLOB_NOCHECK, GLOB_NOESCAPE, GLOB_BRACE, GLOB_ERR>
1730-
* ? false|list{0:''}
1731-
* : false|list<never>
1732-
* )
1733-
* )
1734-
* : (F is int-mask<GLOB_MARK, GLOB_NOSORT, GLOB_NOESCAPE, GLOB_BRACE, GLOB_ONLYDIR, GLOB_ERR>
1735-
* ? false|list<non-empty-string>
1736-
* : (F is int-mask<GLOB_MARK, GLOB_NOSORT, GLOB_NOCHECK, GLOB_NOESCAPE, GLOB_BRACE, GLOB_ERR>
1737-
* ? false|list{0:non-empty-string, ...<non-empty-string>}
1738-
* : false|list<non-empty-string>
1739-
* )
1740-
* )
1741-
* )
1742-
* @psalm-ignore-falsable-return
1743-
*/
1744-
function glob (string $pattern, int $flags = 0): array|false {}
1745-
1746-
1720+
if (defined('GLOB_BRACE')) {
1721+
/**
1722+
* @psalm-template P of string
1723+
* @psalm-template F of int-mask<GLOB_MARK, GLOB_NOSORT, GLOB_NOCHECK, GLOB_NOESCAPE, GLOB_BRACE, GLOB_ONLYDIR, GLOB_ERR>
1724+
* @psalm-param P $pattern
1725+
* @psalm-param F $flags
1726+
* @psalm-return (
1727+
* P is ''
1728+
* ? (F is int-mask<GLOB_MARK, GLOB_NOSORT, GLOB_NOESCAPE, GLOB_BRACE, GLOB_ONLYDIR, GLOB_ERR>
1729+
* ? false|list<never>
1730+
* : (F is int-mask<GLOB_MARK, GLOB_NOSORT, GLOB_NOCHECK, GLOB_NOESCAPE, GLOB_BRACE, GLOB_ERR>
1731+
* ? false|list{0:''}
1732+
* : false|list<never>
1733+
* )
1734+
* )
1735+
* : (F is int-mask<GLOB_MARK, GLOB_NOSORT, GLOB_NOESCAPE, GLOB_BRACE, GLOB_ONLYDIR, GLOB_ERR>
1736+
* ? false|list<non-empty-string>
1737+
* : (F is int-mask<GLOB_MARK, GLOB_NOSORT, GLOB_NOCHECK, GLOB_NOESCAPE, GLOB_BRACE, GLOB_ERR>
1738+
* ? false|list{0:non-empty-string, ...<non-empty-string>}
1739+
* : false|list<non-empty-string>
1740+
* )
1741+
* )
1742+
* )
1743+
* @psalm-ignore-falsable-return
1744+
*/
1745+
function glob (string $pattern, int $flags = 0): array|false {}
1746+
} else {
1747+
/**
1748+
* @psalm-template P of string
1749+
* @psalm-template F of int-mask<GLOB_MARK, GLOB_NOSORT, GLOB_NOCHECK, GLOB_NOESCAPE, GLOB_ONLYDIR, GLOB_ERR>
1750+
* @psalm-param P $pattern
1751+
* @psalm-param F $flags
1752+
* @psalm-return (
1753+
* P is ''
1754+
* ? (F is int-mask<GLOB_MARK, GLOB_NOSORT, GLOB_NOESCAPE, GLOB_ONLYDIR, GLOB_ERR>
1755+
* ? false|list<never>
1756+
* : (F is int-mask<GLOB_MARK, GLOB_NOSORT, GLOB_NOCHECK, GLOB_NOESCAPE, GLOB_ERR>
1757+
* ? false|list{0:''}
1758+
* : false|list<never>
1759+
* )
1760+
* )
1761+
* : (F is int-mask<GLOB_MARK, GLOB_NOSORT, GLOB_NOESCAPE, GLOB_ONLYDIR, GLOB_ERR>
1762+
* ? false|list<non-empty-string>
1763+
* : (F is int-mask<GLOB_MARK, GLOB_NOSORT, GLOB_NOCHECK, GLOB_NOESCAPE, GLOB_ERR>
1764+
* ? false|list{0:non-empty-string, ...<non-empty-string>}
1765+
* : false|list<non-empty-string>
1766+
* )
1767+
* )
1768+
* )
1769+
* @psalm-ignore-falsable-return
1770+
*/
1771+
function glob (string $pattern, int $flags = 0): array|false {}
1772+
}
17471773

tests/CoreStubsTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,12 @@ function takesList(array $list): void {}
406406
takesList(glob( '' ));
407407
PHP,
408408
];
409+
yield 'glob accepts GLOB_BRACE' => [
410+
'code' => <<<'PHP'
411+
<?php
412+
$globBrace = glob('abc', GLOB_BRACE);
413+
PHP,
414+
];
409415
}
410416

411417
public function providerInvalidCodeParse(): iterable

0 commit comments

Comments
 (0)