Skip to content

Commit 43e7d86

Browse files
committed
Release v1.2.0: Security improvements, performance optimizations, and version management
1 parent a4a34ab commit 43e7d86

File tree

4 files changed

+89
-12
lines changed

4 files changed

+89
-12
lines changed

src/Cache/SwooleCacheAdapter.php

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,25 @@ public function get(string $key, callable $callback, ?float $beta = null, ?array
3030
$item = $this->table->get($fullKey);
3131
if ($item && isset($item['value']) && isset($item['expires'])) {
3232
if ($item['expires'] > \time()) {
33-
return \unserialize($item['value']);
33+
try {
34+
// Use error suppression with validation for security
35+
$value = @\unserialize($item['value'], ['allowed_classes' => true]);
36+
if ($value === false && $item['value'] !== \serialize(false)) {
37+
// Invalid serialized data, remove corrupted entry
38+
$this->table->del($fullKey);
39+
// Fall through to callback
40+
} else {
41+
return $value;
42+
}
43+
} catch (\Throwable $e) {
44+
// Corrupted cache entry, remove it
45+
$this->table->del($fullKey);
46+
// Fall through to callback
47+
}
48+
} else {
49+
// Expired, remove it
50+
$this->table->del($fullKey);
3451
}
35-
// Expired, remove it
36-
$this->table->del($fullKey);
3752
}
3853
}
3954

src/Queue/SwooleQueue.php

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,18 @@ public function pop(): mixed
9696
$this->head->set(($head + 1) % $this->maxSize);
9797
$this->sizeCounter->decrement();
9898

99-
return \unserialize($item['value']);
99+
try {
100+
// Use error suppression with validation for security
101+
$value = @\unserialize($item['value'], ['allowed_classes' => true]);
102+
if ($value === false && $item['value'] !== \serialize(false)) {
103+
// Invalid serialized data
104+
return null;
105+
}
106+
return $value;
107+
} catch (\Throwable $e) {
108+
// Corrupted queue entry
109+
return null;
110+
}
100111
} finally {
101112
$this->lock->unlock();
102113
}
@@ -120,7 +131,22 @@ public function peek(): mixed
120131
$key = 'item_' . $head;
121132
$item = $this->table->get($key);
122133

123-
return $item ? \unserialize($item['value']) : null;
134+
if (!$item) {
135+
return null;
136+
}
137+
138+
try {
139+
// Use error suppression with validation for security
140+
$value = @\unserialize($item['value'], ['allowed_classes' => true]);
141+
if ($value === false && $item['value'] !== \serialize(false)) {
142+
// Invalid serialized data
143+
return null;
144+
}
145+
return $value;
146+
} catch (\Throwable $e) {
147+
// Corrupted queue entry
148+
return null;
149+
}
124150
} finally {
125151
$this->lock->unlock();
126152
}

src/Server/HttpServerManager.php

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -271,10 +271,18 @@ private function convertSwooleRequestToSymfony($swooleRequest): Request
271271
$headers = $swooleRequest->header ?? [];
272272
$server = $swooleRequest->server ?? [];
273273

274+
// Validate and sanitize input to prevent header injection
275+
$maxHeaderLength = 8192; // RFC 7230 limit
276+
$maxUriLength = 8192; // RFC 7230 limit
277+
274278
// Convert Swoole server variables to PHP $_SERVER format
275279
$serverVars = [];
276280
foreach ($server as $key => $value) {
277-
$serverVars[\strtoupper($key)] = $value;
281+
// Sanitize key
282+
$key = \strtoupper((string) $key);
283+
// Sanitize value - prevent header injection
284+
$value = \is_string($value) ? \substr((string) $value, 0, $maxHeaderLength) : $value;
285+
$serverVars[$key] = $value;
278286
}
279287

280288
// Add headers to server vars
@@ -283,13 +291,19 @@ private function convertSwooleRequestToSymfony($swooleRequest): Request
283291
$serverVars[$key] = $value;
284292
}
285293

286-
// Set basic server vars
287-
$serverVars['REQUEST_METHOD'] = $server['request_method'] ?? 'GET';
288-
$serverVars['REQUEST_URI'] = $server['request_uri'] ?? '/';
294+
// Set basic server vars with validation
295+
$requestUri = $server['request_uri'] ?? '/';
296+
// Validate URI length
297+
if (\strlen($requestUri) > $maxUriLength) {
298+
$requestUri = \substr($requestUri, 0, $maxUriLength);
299+
}
300+
301+
$serverVars['REQUEST_METHOD'] = \strtoupper($server['request_method'] ?? 'GET');
302+
$serverVars['REQUEST_URI'] = $requestUri;
289303
$serverVars['SERVER_PROTOCOL'] = $server['server_protocol'] ?? 'HTTP/1.1';
290304
$serverVars['SERVER_NAME'] = $server['server_name'] ?? 'localhost';
291-
$serverVars['SERVER_PORT'] = $server['server_port'] ?? 80;
292-
$serverVars['QUERY_STRING'] = $server['query_string'] ?? '';
305+
$serverVars['SERVER_PORT'] = (int) ($server['server_port'] ?? 80);
306+
$serverVars['QUERY_STRING'] = \substr((string) ($server['query_string'] ?? ''), 0, $maxHeaderLength);
293307

294308
// Handle content type for POST requests
295309
if (isset($headers['content-type'])) {
@@ -335,6 +349,22 @@ private function sendResponse($swooleResponse, Response $response): void
335349
}
336350
}
337351

352+
// Add security headers if not already set (only in production)
353+
if (!$this->kernel->isDebug()) {
354+
$securityHeaders = [
355+
'X-Content-Type-Options' => 'nosniff',
356+
'X-Frame-Options' => 'DENY',
357+
'X-XSS-Protection' => '1; mode=block',
358+
'Referrer-Policy' => 'strict-origin-when-cross-origin',
359+
];
360+
361+
foreach ($securityHeaders as $header => $value) {
362+
if (!$response->headers->has($header)) {
363+
$swooleResponse->header($header, $value);
364+
}
365+
}
366+
}
367+
338368
// Get content
339369
$content = $response->getContent();
340370

src/SwooleBundle.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,20 @@
77
use Symfony\Component\HttpKernel\Bundle\Bundle;
88

99
/**
10-
* Swoole Bundle for Symfony 7
10+
* Swoole Bundle for Symfony 7/8
1111
*
1212
* High-performance bundle exploiting all Swoole 6.1 capabilities
1313
*
1414
* @author toadbeatz
1515
*/
1616
class SwooleBundle extends Bundle
1717
{
18+
/**
19+
* Bundle version
20+
* This is the single source of truth for the bundle version
21+
*/
22+
public const VERSION = '1.2.0';
23+
1824
public function getPath(): string
1925
{
2026
return \dirname(__DIR__);

0 commit comments

Comments
 (0)