Skip to content

Commit a41f58f

Browse files
authored
Upgrade Psalm to 6.13 (#1973)
* Use `get_debug_type` for error reporting * Harden code against error cases * Upgrade Psalm to 6.13
1 parent 1ca722e commit a41f58f

16 files changed

+84
-17
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515

1616
- Apply new CodingStandard from latest php-cs-fixer.
1717
- Fix PHP 8.5 deprecation by avoiding using `null` as an array offset.
18+
- Harden code against error cases
1819

1920
### Fixed
2021

2122
- Buffer the response in temporary file to avoid issues when stream is used by another request's body
2223

23-
2424
## 1.27.1
2525

2626
### Fixed

src/Credentials/ContainerProvider.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ private function isLoopBackAddress(string $host)
118118
// Convert the IP address to binary format
119119
$packedIp = inet_pton($host);
120120

121+
if (false === $packedIp) {
122+
return false;
123+
}
124+
121125
// Check if the IP is in the 127.0.0.0/8 range
122126
if (4 === \strlen($packedIp)) {
123127
return 127 === \ord($packedIp[0]);

src/Credentials/IniFileLoader.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public function loadProfiles(array $filepaths): array
6262

6363
foreach ($this->parseIniFile($filepath) as $name => $profile) {
6464
$name = preg_replace('/^profile /', '', (string) $name);
65+
\assert(null !== $name);
6566
if (!isset($profilesData[$name])) {
6667
$profilesData[$name] = array_map('trim', $profile);
6768
} else {
@@ -96,8 +97,16 @@ private function getHomeDir(): string
9697
*/
9798
private function parseIniFile(string $filepath): array
9899
{
100+
$content = file_get_contents($filepath);
101+
102+
if (false === $content) {
103+
$this->logger->warning('The ini file {path} is not readable.', ['path' => $filepath]);
104+
105+
return [];
106+
}
107+
99108
if (false === $data = parse_ini_string(
100-
preg_replace('/^#/m', ';', file_get_contents($filepath)),
109+
preg_replace('/^#/m', ';', $content),
101110
true,
102111
\INI_SCANNER_RAW
103112
)) {

src/Credentials/SsoTokenProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ private function dumpSsoToken(string $sessionName, array $tokenData): void
124124
{
125125
$filepath = \sprintf('%s/.aws/sso/cache/%s.json', $this->getHomeDir(), sha1($sessionName));
126126

127-
file_put_contents($filepath, json_encode(array_filter($tokenData)));
127+
file_put_contents($filepath, json_encode(array_filter($tokenData), \JSON_THROW_ON_ERROR));
128128
}
129129

130130
/**

src/Credentials/TokenFileLoader.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ public function getTokenFileContent(string $tokenFile): string
2323

2424
$tokenDir = \dirname($tokenFile);
2525
$tokenLink = readlink($tokenFile);
26-
clearstatcache(true, $tokenDir . \DIRECTORY_SEPARATOR . $tokenLink);
27-
clearstatcache(true, $tokenDir . \DIRECTORY_SEPARATOR . \dirname($tokenLink));
26+
if (false !== $tokenLink) {
27+
clearstatcache(true, $tokenDir . \DIRECTORY_SEPARATOR . $tokenLink);
28+
clearstatcache(true, $tokenDir . \DIRECTORY_SEPARATOR . \dirname($tokenLink));
29+
}
2830
clearstatcache(true, $tokenFile);
2931

3032
if (false === $token = file_get_contents($tokenFile)) {

src/Stream/CallableStream.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public static function create($content, int $chunkSize = 64 * 1024): CallableStr
4545
return new self($content, $chunkSize);
4646
}
4747

48-
throw new InvalidArgument(\sprintf('Expect content to be a "callable". "%s" given.', \is_object($content) ? \get_class($content) : \gettype($content)));
48+
throw new InvalidArgument(\sprintf('Expect content to be a "callable". "%s" given.', get_debug_type($content)));
4949
}
5050

5151
public function length(): ?int
@@ -62,7 +62,7 @@ public function getIterator(): \Traversable
6262
{
6363
while (true) {
6464
if (!\is_string($data = ($this->content)($this->chunkSize))) {
65-
throw new InvalidArgument(\sprintf('The return value of content callback must be a string, %s returned.', \is_object($data) ? \get_class($data) : \gettype($data)));
65+
throw new InvalidArgument(\sprintf('The return value of content callback must be a string, %s returned.', get_debug_type($data)));
6666
}
6767
if ('' === $data) {
6868
break;

src/Stream/FixedSizeStream.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public function getIterator(): \Traversable
5656
$chunk = '';
5757
foreach ($this->content as $buffer) {
5858
if (!\is_string($buffer)) {
59-
throw new InvalidArgument(\sprintf('The return value of content callback must be a string, %s returned.', \is_object($buffer) ? \get_class($buffer) : \gettype($buffer)));
59+
throw new InvalidArgument(\sprintf('The return value of content callback must be a string, %s returned.', get_debug_type($buffer)));
6060
}
6161

6262
$chunk .= $nextBytes = substr($buffer, 0, $this->chunkSize - \strlen($chunk));

src/Stream/IterableStream.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public static function create($content): IterableStream
3636
return new self($content);
3737
}
3838

39-
throw new InvalidArgument(\sprintf('Expect content to be an iterable. "%s" given.', \is_object($content) ? \get_class($content) : \gettype($content)));
39+
throw new InvalidArgument(\sprintf('Expect content to be an iterable. "%s" given.', get_debug_type($content)));
4040
}
4141

4242
public function length(): ?int

src/Stream/ResourceStream.php

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace AsyncAws\Core\Stream;
44

55
use AsyncAws\Core\Exception\InvalidArgument;
6+
use AsyncAws\Core\Exception\RuntimeException;
67

78
/**
89
* Convert a resource into a Stream.
@@ -48,7 +49,7 @@ public static function create($content, int $chunkSize = 64 * 1024): ResourceStr
4849
return new self($content, $chunkSize);
4950
}
5051

51-
throw new InvalidArgument(\sprintf('Expect content to be a "resource". "%s" given.', \is_object($content) ? \get_class($content) : \gettype($content)));
52+
throw new InvalidArgument(\sprintf('Expect content to be a "resource". "%s" given.', get_debug_type($content)));
5253
}
5354

5455
public function length(): ?int
@@ -62,7 +63,13 @@ public function stringify(): string
6263
throw new InvalidArgument('Unable to seek the content.');
6364
}
6465

65-
return stream_get_contents($this->content);
66+
$data = stream_get_contents($this->content);
67+
68+
if (false === $data) {
69+
throw new RuntimeException('Unable to read the content.');
70+
}
71+
72+
return $data;
6673
}
6774

6875
public function getIterator(): \Traversable
@@ -72,7 +79,13 @@ public function getIterator(): \Traversable
7279
}
7380

7481
while (!feof($this->content)) {
75-
yield fread($this->content, $this->chunkSize);
82+
$data = fread($this->content, $this->chunkSize);
83+
84+
if (false === $data) {
85+
throw new RuntimeException('Unable to read the content.');
86+
}
87+
88+
yield $data;
7689
}
7790
}
7891

@@ -88,6 +101,10 @@ public function hash(string $algo = 'sha256', bool $raw = false): string
88101
{
89102
$pos = ftell($this->content);
90103

104+
if (false === $pos) {
105+
throw new InvalidArgument('Unable to read the content position.');
106+
}
107+
91108
if ($pos > 0 && -1 === fseek($this->content, 0)) {
92109
throw new InvalidArgument('Unable to seek the content.');
93110
}

src/Stream/ResponseBodyResourceStream.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,23 @@ public function __toString(): string
3737
public function getChunks(): iterable
3838
{
3939
$pos = ftell($this->resource);
40+
if (false === $pos) {
41+
throw new RuntimeException('Unable to read the content position.');
42+
}
43+
4044
if (0 !== $pos && !rewind($this->resource)) {
4145
throw new RuntimeException('The stream is not rewindable');
4246
}
4347

4448
try {
4549
while (!feof($this->resource)) {
46-
yield fread($this->resource, 64 * 1024);
50+
$data = fread($this->resource, 64 * 1024);
51+
52+
if (false === $data) {
53+
throw new RuntimeException('Unable to read the content.');
54+
}
55+
56+
yield $data;
4757
}
4858
} finally {
4959
fseek($this->resource, $pos);
@@ -57,12 +67,22 @@ public function getContentAsString(): string
5767
{
5868
$pos = ftell($this->resource);
5969

70+
if (false === $pos) {
71+
throw new RuntimeException('Failed to read the stream position.');
72+
}
73+
6074
try {
6175
if (!rewind($this->resource)) {
6276
throw new RuntimeException('Failed to rewind the stream');
6377
}
6478

65-
return stream_get_contents($this->resource);
79+
$data = stream_get_contents($this->resource);
80+
81+
if (false === $data) {
82+
throw new RuntimeException('Unable to read the content.');
83+
}
84+
85+
return $data;
6686
} finally {
6787
fseek($this->resource, $pos);
6888
}

0 commit comments

Comments
 (0)