mirror of
https://github.com/phpredis/phpredis.git
synced 2026-06-19 07:35:31 +00:00
fix: Accept null for $seeds in RedisCluster::__construct
The stub declares $seeds as ?array but the C code used format specifier 'a' (non-nullable) instead of 'a!' in zend_parse_method_parameters. This caused new RedisCluster(null, null) to throw TypeError instead of RedisClusterException, contradicting the declared type signature. Also treat z_seeds == NULL the same as ZEND_NUM_ARGS() < 2 so that explicitly passing null falls through to INI-based seed loading, matching the behaviour when the argument is omitted entirely. Fixes GH-2810. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
committed by
Michael Grunder
parent
741abf09ec
commit
409508afa2
+2
-2
@@ -353,7 +353,7 @@ PHP_METHOD(RedisCluster, __construct) {
|
||||
|
||||
// Parse arguments
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
|
||||
"Os!|addbza!", &object, redis_cluster_ce, &name,
|
||||
"Os!|a!ddbza!", &object, redis_cluster_ce, &name,
|
||||
&name_len, &z_seeds, &timeout, &read_timeout,
|
||||
&persistent, &z_auth, &context) == FAILURE)
|
||||
{
|
||||
@@ -361,7 +361,7 @@ PHP_METHOD(RedisCluster, __construct) {
|
||||
}
|
||||
|
||||
/* If we've got a string try to load from INI */
|
||||
if (ZEND_NUM_ARGS() < 2) {
|
||||
if (ZEND_NUM_ARGS() < 2 || z_seeds == NULL) {
|
||||
if (name_len == 0) { // Require a name
|
||||
CLUSTER_THROW_EXCEPTION("You must specify a name or pass seeds!", 0);
|
||||
}
|
||||
|
||||
@@ -70,6 +70,40 @@ class Redis_Cluster_Test extends Redis_Test {
|
||||
public function testSession_noUnlockOfOtherProcess() { $this->markTestSkipped(); }
|
||||
public function testSession_lockWaitTime() { $this->markTestSkipped(); }
|
||||
|
||||
/* Regression test for GH #2810 */
|
||||
public function testConstructNullSeeds() {
|
||||
/* new RedisCluster(null, null) must not throw TypeError.
|
||||
* $seeds is declared ?array so null is a valid argument. */
|
||||
$thrown = false;
|
||||
try {
|
||||
new RedisCluster(null, null);
|
||||
} catch (\Throwable $e) {
|
||||
$thrown = true;
|
||||
$this->assertFalse($e instanceof \TypeError);
|
||||
}
|
||||
$this->assertTrue($thrown);
|
||||
|
||||
/* Passing an empty array must also not throw TypeError (control). */
|
||||
$thrown = false;
|
||||
try {
|
||||
new RedisCluster(null, []);
|
||||
} catch (\Throwable $e) {
|
||||
$thrown = true;
|
||||
$this->assertFalse($e instanceof \TypeError);
|
||||
}
|
||||
$this->assertTrue($thrown);
|
||||
|
||||
/* Both (null) and (null, null) mean "no name, no seeds" and must
|
||||
* produce the same exception type. */
|
||||
$ex1 = $ex2 = null;
|
||||
try { new RedisCluster(null); }
|
||||
catch (\Throwable $e) { $ex1 = get_class($e); }
|
||||
try { new RedisCluster(null, null); }
|
||||
catch (\Throwable $e) { $ex2 = get_class($e); }
|
||||
$this->assertTrue($ex1 !== null);
|
||||
$this->assertEquals($ex1, $ex2);
|
||||
}
|
||||
|
||||
private function loadSeedsFromHostPort($host, $port) {
|
||||
try {
|
||||
$rc = new RedisCluster(NULL, ["$host:$port"], 1, 1, true, $this->getAuth());
|
||||
|
||||
Reference in New Issue
Block a user