Skip to content

Commit b877837

Browse files
constantablefabpot
authored andcommitted
[Cache] Improve dbindex DSN parameter parsing
1 parent b437362 commit b877837

File tree

2 files changed

+81
-2
lines changed

2 files changed

+81
-2
lines changed

src/Symfony/Component/Cache/Tests/Traits/RedisTraitTest.php

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use PHPUnit\Framework\SkippedTestSuiteError;
1515
use PHPUnit\Framework\TestCase;
16+
use Symfony\Component\Cache\Exception\InvalidArgumentException;
1617
use Symfony\Component\Cache\Traits\RedisTrait;
1718

1819
/**
@@ -133,4 +134,78 @@ public function testPconnectSelectsCorrectDatabase()
133134
ini_set('redis.pconnect.connection_limit', $prevPoolSize);
134135
}
135136
}
137+
138+
/**
139+
* @dataProvider provideDbIndexDsnParameter
140+
*/
141+
public function testDbIndexDsnParameter(string $dsn, int $expectedDb)
142+
{
143+
if (!getenv('REDIS_AUTHENTICATED_HOST')) {
144+
self::markTestSkipped('REDIS_AUTHENTICATED_HOST env var is not defined.');
145+
}
146+
147+
$mock = new class () {
148+
use RedisTrait;
149+
};
150+
$connection = $mock::createConnection($dsn);
151+
self::assertSame($expectedDb, $connection->getDbNum());
152+
}
153+
154+
public static function provideDbIndexDsnParameter(): array
155+
{
156+
return [
157+
[
158+
'redis://:p%40ssword@'.getenv('REDIS_AUTHENTICATED_HOST'),
159+
0,
160+
],
161+
[
162+
'redis:?host['.getenv('REDIS_HOST').']',
163+
0,
164+
],
165+
[
166+
'redis:?host['.getenv('REDIS_HOST').']&dbindex=1',
167+
1,
168+
],
169+
[
170+
'redis://:p%40ssword@'.getenv('REDIS_AUTHENTICATED_HOST').'?dbindex=2',
171+
2,
172+
],
173+
[
174+
'redis://:p%40ssword@'.getenv('REDIS_AUTHENTICATED_HOST').'/4',
175+
4,
176+
],
177+
[
178+
'redis://:p%40ssword@'.getenv('REDIS_AUTHENTICATED_HOST').'/?dbindex=5',
179+
5,
180+
],
181+
];
182+
}
183+
184+
/**
185+
* @dataProvider provideInvalidDbIndexDsnParameter
186+
*/
187+
public function testInvalidDbIndexDsnParameter(string $dsn)
188+
{
189+
if (!getenv('REDIS_AUTHENTICATED_HOST')) {
190+
self::markTestSkipped('REDIS_AUTHENTICATED_HOST env var is not defined.');
191+
}
192+
$this->expectException(InvalidArgumentException::class);
193+
194+
$mock = new class () {
195+
use RedisTrait;
196+
};
197+
$mock::createConnection($dsn);
198+
}
199+
200+
public static function provideInvalidDbIndexDsnParameter(): array
201+
{
202+
return [
203+
[
204+
'redis://:p%40ssword@'.getenv('REDIS_AUTHENTICATED_HOST').'/abc'
205+
],
206+
[
207+
'redis://:p%40ssword@'.getenv('REDIS_AUTHENTICATED_HOST').'/3?dbindex=6'
208+
]
209+
];
210+
}
136211
}

src/Symfony/Component/Cache/Traits/RedisTrait.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,10 @@ public static function createConnection(string $dsn, array $options = [])
152152
if (isset($params['host']) || isset($params['path'])) {
153153
if (!isset($params['dbindex']) && isset($params['path'])) {
154154
if (preg_match('#/(\d+)?$#', $params['path'], $m)) {
155-
$params['dbindex'] = $m[1] ?? '0';
155+
$params['dbindex'] = $m[1] ?? $query['dbindex'] ?? '0';
156156
$params['path'] = substr($params['path'], 0, -\strlen($m[0]));
157157
} elseif (isset($params['host'])) {
158-
throw new InvalidArgumentException('Invalid Redis DSN: query parameter "dbindex" must be a number.');
158+
throw new InvalidArgumentException('Invalid Redis DSN: parameter "dbindex" must be a number.');
159159
}
160160
}
161161

@@ -170,6 +170,10 @@ public static function createConnection(string $dsn, array $options = [])
170170
throw new InvalidArgumentException('Invalid Redis DSN: missing host.');
171171
}
172172

173+
if (isset($params['dbindex'], $query['dbindex']) && $params['dbindex'] !== $query['dbindex']) {
174+
throw new InvalidArgumentException('Invalid Redis DSN: path and query "dbindex" parameters mismatch.');
175+
}
176+
173177
$params += $query + $options + self::$defaultConnectionOptions;
174178

175179
if (isset($params['redis_sentinel']) && !class_exists(\Predis\Client::class) && !class_exists(\RedisSentinel::class)) {

0 commit comments

Comments
 (0)