Skip to content

Commit c964e02

Browse files
author
Jonathon Hill
committed
Level 7 static analysis
1 parent 9ce9165 commit c964e02

File tree

10 files changed

+102
-46
lines changed

10 files changed

+102
-46
lines changed

phpstan.neon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
parameters:
2-
level: 6
2+
level: 7
33
paths:
44
- src
55
- tests

src/Factory.php

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -92,27 +92,59 @@ public function configFromSystem(): Config
9292
$config = new Config();
9393

9494
$config->setSerializeHandler(
95-
Serializers\Factory::auto(ini_get('session.serialize_handler'))
95+
Serializers\Factory::auto(ini_get('session.serialize_handler') ?: null)
9696
);
9797

98-
$config->setName(ini_get('session.name'));
98+
if (ini_get('session.name') !== false) {
99+
$config->setName(ini_get('session.name'));
100+
}
101+
102+
if (ini_get('session.cookie_lifetime') !== false) {
103+
$config->setCookieLifetime((int) ini_get('session.cookie_lifetime'));
104+
}
105+
106+
if (ini_get('session.cookie_path') !== false) {
107+
$config->setCookiePath(ini_get('session.cookie_path'));
108+
}
109+
110+
if (ini_get('session.cookie_domain') !== false) {
111+
$config->setCookieDomain(ini_get('session.cookie_domain'));
112+
}
99113

100-
$config->setCookieLifetime((int) ini_get('session.cookie_lifetime'));
101-
$config->setCookiePath(ini_get('session.cookie_path'));
102-
$config->setCookieDomain(ini_get('session.cookie_domain'));
103114
$config->setCookieSecure((bool) ini_get('session.cookie_secure'));
104115
$config->setCookieHttpOnly((bool) ini_get('session.cookie_httponly'));
105-
$config->setCookieSameSite(ini_get('session.cookie_samesite'));
106116

107-
$config->setCacheLimiter(ini_get('session.cache_limiter'));
108-
$config->setCacheExpire((int) ini_get('session.cache_expire'));
117+
if (ini_get('session.cookie_samesite') !== false) {
118+
$config->setCookieSameSite(ini_get('session.cookie_samesite'));
119+
}
120+
121+
if (ini_get('session.cache_limiter') !== false) {
122+
$config->setCacheLimiter(ini_get('session.cache_limiter'));
123+
}
124+
125+
if (ini_get('session.cache_expire') !== false) {
126+
$config->setCacheExpire((int) ini_get('session.cache_expire'));
127+
}
128+
129+
if (ini_get('session.gc_probability') !== false) {
130+
$config->setGcProbability((int) ini_get('session.gc_probability'));
131+
}
132+
133+
if (ini_get('session.gc_divisor') !== false) {
134+
$config->setGcDivisor((int) ini_get('session.gc_divisor'));
135+
}
109136

110-
$config->setGcProbability((int) ini_get('session.gc_probability'));
111-
$config->setGcDivisor((int) ini_get('session.gc_divisor'));
112-
$config->setGcMaxLifetime((int) ini_get('session.gc_maxlifetime'));
137+
if (ini_get('session.gc_maxlifetime') !== false) {
138+
$config->setGcMaxLifetime((int) ini_get('session.gc_maxlifetime'));
139+
}
113140

114-
$config->setSidLength((int) ini_get('session.sid_length'));
115-
$config->setSidBitsPerCharacter((int) ini_get('session.sid_bits_per_character'));
141+
if (ini_get('session.sid_length') !== false) {
142+
$config->setSidLength((int) ini_get('session.sid_length'));
143+
}
144+
145+
if (ini_get('session.sid_bits_per_character') !== false) {
146+
$config->setSidBitsPerCharacter((int) ini_get('session.sid_bits_per_character'));
147+
}
116148

117149
$config->setLazyWrite((bool) ini_get('session.lazy_write'));
118150

src/Handlers/ArrayHandler.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ class ArrayHandler implements
2929
private SessionId $sid;
3030

3131
/**
32-
* @var array<string, array{data: mixed, meta: array{id: string, last_modified: float, destroyed?: float}}>
32+
* @var array<string, array{data: mixed, meta: array{id: string, last_modified: float, destroyed?: bool}}>
3333
*/
3434
private array $store;
3535

3636
/**
37-
* @param array<string, array{data: mixed, meta: array{id: string, last_modified: float, destroyed?: float}}> $store
37+
* @param array<string, array{data: mixed, meta: array{id: string, last_modified: float, destroyed?: bool}}> $store
3838
*/
3939
public function __construct(Config $config, array $store = [])
4040
{
@@ -196,7 +196,7 @@ public function count(): int
196196
}
197197

198198
/**
199-
* @return array<string, array{data: mixed, meta: array{id: string, last_modified: float, destroyed?: float}}>
199+
* @return array<string, array{data: mixed, meta: array{id: string, last_modified: float, destroyed?: bool}}>
200200
*/
201201
public function toArray(): array
202202
{

src/Handlers/FileHandler.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ class FileHandler implements
3131

3232
public function __construct(Config $config)
3333
{
34-
// required for SessionIdTrait
3534
$this->sid = new SessionId($config);
3635
}
3736

@@ -89,7 +88,9 @@ public function destroy($id): bool
8988

9089
public function gc($maxlifetime): bool
9190
{
92-
foreach (glob($this->getFilePath('*')) as $file) {
91+
$files = glob($this->getFilePath('*')) ?: [];
92+
93+
foreach ($files as $file) {
9394
if (file_exists($file) && time() > filemtime($file) + $maxlifetime) {
9495
unlink($file);
9596
}
@@ -120,7 +121,7 @@ public function updateTimestamp($id, $data): bool
120121

121122
public function count(): int
122123
{
123-
return count(glob($this->getFilePath('*')));
124+
return count(glob($this->getFilePath('*')) ?: []);
124125
}
125126

126127
/**

src/Handlers/RedisHandler.php

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
use Compwright\PhpSession\Config;
1010
use Compwright\PhpSession\SessionId;
11+
use InvalidArgumentException;
1112
use MatthiasMullie\Scrapbook\Adapters\Redis as RedisKeyValueStore;
1213
use Redis;
1314
use RuntimeException;
@@ -38,24 +39,41 @@ public function open($path, $name): bool
3839
// Parse redis connection settings from save path
3940
$query = [];
4041
$config = parse_url($path);
42+
if ($config === false) {
43+
throw new InvalidArgumentException('Invalid $path');
44+
}
4145
if (!empty($config['query'])) {
4246
parse_str($config['query'], $query);
4347
}
4448

4549
$redis = new Redis();
4650

47-
if (!$redis->connect($config['host'], (int) $config['port'])) {
51+
if (empty($config['host'])) {
52+
throw new InvalidArgumentException('Missing host or socket in $path');
53+
}
54+
55+
$port = isset($config['port']) && !is_null($config['port'])
56+
? (int) $config['port']
57+
: null;
58+
59+
if (!$redis->connect($config['host'], $port)) {
4860
unset($redis);
4961
return false;
5062
}
5163

52-
if (!$redis->select((int) ($query['database'] ?? 0))) {
64+
$database = isset($query['database']) && !is_null($query['database'])
65+
? (int) $query['database']
66+
: 0;
67+
68+
if (!$redis->select($database)) {
5369
$redis->close();
5470
unset($redis);
5571
return false;
5672
}
5773

58-
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_NONE);
74+
if (!$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_NONE)) {
75+
return false;
76+
}
5977

6078
$this->redis = $redis;
6179
$this->store = new RedisKeyValueStore($redis);

src/Manager.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
declare(strict_types=1);
44

5-
// phpcs:ignoreFile PSR1.Methods.CamelCapsMethodName.NotCamelCaps
6-
75
namespace Compwright\PhpSession;
86

97
use InvalidArgumentException;
@@ -346,7 +344,11 @@ public function start(): bool
346344
$this->sid->create_sid(),
347345
[]
348346
);
349-
$handler->write($this->currentSession->getId(), $this->encode());
347+
$encoded = $this->encode();
348+
if ($encoded === false) {
349+
return false;
350+
}
351+
$handler->write($this->currentSession->getId(), $encoded);
350352
}
351353

352354
$id = $this->currentSession->getId();

src/Middleware/SessionCacheControlMiddleware.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,14 @@ public function process(
3333

3434
$handler = $config->getSaveHandler();
3535

36-
$lastUpdated = $handler instanceof SessionLastModifiedTimestampHandlerInterface
37-
? (int) ceil($handler->getTimestamp($manager->id()))
38-
: time();
36+
if ($handler instanceof SessionLastModifiedTimestampHandlerInterface) {
37+
$lastUpdated = $handler->getTimestamp($manager->id()) ?: time();
38+
if (is_float($lastUpdated)) {
39+
$lastUpdated = (int) ceil($lastUpdated);
40+
}
41+
} else {
42+
$lastUpdated = time();
43+
}
3944

4045
$cacheControl = CacheControl::createHeaders(
4146
$config->getCacheLimiter(),

src/Middleware/SessionCookieMiddleware.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public function process(
3737
if ($manager->id() !== $sid) {
3838
$config = $manager->getConfig();
3939
return FigResponseCookies::set($response, SessionCookie::create(
40-
$manager->name(),
40+
$manager->name() ?: '',
4141
$manager->id(),
4242
$config->getCookieLifetime(),
4343
$config->getCookieDomain(),

src/SessionId.php

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
declare(strict_types=1);
44

5-
// phpcs:ignoreFile PSR1.Methods.CamelCapsMethodName.NotCamelCaps
6-
75
namespace Compwright\PhpSession;
86

97
use SessionIdInterface;
@@ -25,11 +23,11 @@ public function __toString(): string
2523
public function create_sid(): string
2624
{
2725
$prefix = $this->config->getSidPrefix();
28-
$desired_output_length = $this->config->getSidLength() - strlen($prefix);
29-
$bits_per_character = $this->config->getSidBitsPerCharacter();
26+
$desiredOutputLength = $this->config->getSidLength() - strlen($prefix);
27+
$bitsPerCharacter = $this->config->getSidBitsPerCharacter();
3028

31-
$bytes_needed = ceil($desired_output_length * $bits_per_character / 8);
32-
$random_input_bytes = random_bytes((int) $bytes_needed);
29+
$bytesNeeded = (int) ceil($desiredOutputLength * $bitsPerCharacter / 8);
30+
$randomInputBytes = random_bytes(max(1, $bytesNeeded));
3331

3432
// The below is translated from function bin_to_readable in the PHP source
3533
// (ext/session/session.c)
@@ -38,17 +36,17 @@ public function create_sid(): string
3836
$out = '';
3937

4038
$p = 0;
41-
$q = strlen($random_input_bytes);
39+
$q = strlen($randomInputBytes);
4240
$w = 0;
4341
$have = 0;
4442

45-
$mask = (1 << $bits_per_character) - 1;
43+
$mask = (1 << $bitsPerCharacter) - 1;
4644

47-
$chars_remaining = $desired_output_length;
48-
while ($chars_remaining--) {
49-
if ($have < $bits_per_character) {
45+
$charsRemaining = $desiredOutputLength;
46+
while ($charsRemaining--) {
47+
if ($have < $bitsPerCharacter) {
5048
if ($p < $q) {
51-
$byte = ord($random_input_bytes[$p++]);
49+
$byte = ord($randomInputBytes[$p++]);
5250
$w |= ($byte << $have);
5351
$have += 8;
5452
} else {
@@ -57,10 +55,10 @@ public function create_sid(): string
5755
}
5856
}
5957

60-
// consume $bits_per_character bits
58+
// consume $bitsPerCharacter bits
6159
$out .= $hexconvtab[$w & $mask];
62-
$w >>= $bits_per_character;
63-
$have -= $bits_per_character;
60+
$w >>= $bitsPerCharacter;
61+
$have -= $bitsPerCharacter;
6462
}
6563

6664
return $prefix . $out;

tests/integration/server/App/config.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
return [
1414
LoggerInterface::class => DI\factory(function () {
1515
$logger = new Logger('access');
16-
$logHandler = new StreamHandler(fopen('php://stdout', 'r+'));
16+
$logHandler = new StreamHandler(STDOUT);
1717
$logHandler->setFormatter(new ColoredLineFormatter());
1818
$logger->pushHandler($logHandler);
1919
return $logger;

0 commit comments

Comments
 (0)