Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f7edee5

Browse files
More robust GEORADIUS COUNT validation
While testing example code for Geo codes I discovered that passing a negative count would cause PhpRedis to hang as it would send an invalid number of arguments to the server.
1 parent a8859b4 commit f7edee5

2 files changed

Lines changed: 38 additions & 9 deletions

File tree

redis_commands.c

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2567,8 +2567,9 @@ int redis_geodist_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
25672567
}
25682568

25692569
/* Helper function to extract optional arguments for GEORADIUS and GEORADIUSBYMEMBER */
2570-
static void get_georadius_opts(HashTable *ht, int *withcoord, int *withdist,
2571-
int *withhash, long *count, geoSortType *sort)
2570+
static int get_georadius_opts(HashTable *ht, int *withcoord, int *withdist,
2571+
int *withhash, long *count, geoSortType *sort
2572+
TSRMLS_DC)
25722573
{
25732574
ulong idx;
25742575
char *optstr;
@@ -2582,7 +2583,13 @@ static void get_georadius_opts(HashTable *ht, int *withcoord, int *withdist,
25822583
ZVAL_DEREF(optval);
25832584
/* If the key is numeric it's a non value option */
25842585
if (zkey) {
2585-
if (ZSTR_LEN(zkey) == 5 && !strcasecmp(ZSTR_VAL(zkey), "count") && Z_TYPE_P(optval) == IS_LONG) {
2586+
if (ZSTR_LEN(zkey) == 5 && !strcasecmp(ZSTR_VAL(zkey), "count")) {
2587+
if (Z_TYPE_P(optval) != IS_LONG || Z_LVAL_P(optval) <= 0) {
2588+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "COUNT must be an integer > 0!");
2589+
return FAILURE;
2590+
}
2591+
2592+
/* Set our count */
25862593
*count = Z_LVAL_P(optval);
25872594
}
25882595
} else {
@@ -2604,6 +2611,9 @@ static void get_georadius_opts(HashTable *ht, int *withcoord, int *withdist,
26042611
}
26052612
}
26062613
} ZEND_HASH_FOREACH_END();
2614+
2615+
/* Success */
2616+
return SUCCESS;
26072617
}
26082618

26092619
/* Helper to append options to a GEORADIUS or GEORADIUSBYMEMBER command */
@@ -2630,7 +2640,7 @@ void append_georadius_opts(smart_string *str, int withcoord, int withdist,
26302640
}
26312641

26322642
/* Append our count if we've got one */
2633-
if (count > 0) {
2643+
if (count) {
26342644
REDIS_CMD_APPEND_SSTR_STATIC(str, "COUNT");
26352645
redis_cmd_append_sstr_long(str, count);
26362646
}
@@ -2659,14 +2669,18 @@ int redis_georadius_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
26592669

26602670
/* Parse any GEORADIUS options we have */
26612671
if (opts != NULL) {
2662-
get_georadius_opts(Z_ARRVAL_P(opts), &withcoord, &withdist, &withhash,
2663-
&count, &sort);
2672+
/* Attempt to parse our options array */
2673+
if (get_georadius_opts(Z_ARRVAL_P(opts), &withcoord, &withdist,
2674+
&withhash, &count, &sort TSRMLS_CC) != SUCCESS)
2675+
{
2676+
return FAILURE;
2677+
}
26642678
}
26652679

26662680
/* Calculate the number of arguments we're going to send, five required plus
26672681
* options. */
26682682
argc = 5 + withcoord + withdist + withhash + (sort != SORT_NONE);
2669-
if (count != 0) argc += 2;
2683+
if (count) argc += 2;
26702684

26712685
/* Begin construction of our command */
26722686
REDIS_CMD_INIT_SSTR_STATIC(&cmdstr, argc, "GEORADIUS");
@@ -2715,12 +2729,17 @@ int redis_georadiusbymember_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s
27152729
}
27162730

27172731
if (opts != NULL) {
2718-
get_georadius_opts(Z_ARRVAL_P(opts), &withcoord, &withdist, &withhash, &count, &sort);
2732+
/* Attempt to parse our options array */
2733+
if (get_georadius_opts(Z_ARRVAL_P(opts), &withcoord, &withdist,
2734+
&withhash, &count, &sort TSRMLS_CC) != SUCCESS)
2735+
{
2736+
return FAILURE;
2737+
}
27192738
}
27202739

27212740
/* Calculate argc */
27222741
argc = 4 + withcoord + withdist + withhash + (sort != SORT_NONE);
2723-
if (count != 0) argc += 2;
2742+
if (count) argc += 2;
27242743

27252744
/* Begin command construction*/
27262745
REDIS_CMD_INIT_SSTR_STATIC(&cmdstr, argc, "GEORADIUSBYMEMBER");

tests/RedisTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4978,13 +4978,23 @@ public function genericGeoRadiusTest($cmd) {
49784978
$this->assertEquals($this->redis->georadius('gk', $lng, $lat, 50000, 'm'), Array('Gridley','Chico'));
49794979
$this->assertEquals($this->redis->georadius('gk', $lng, $lat, 150000, 'ft'), Array('Gridley', 'Chico'));
49804980
$args = Array('georadius', 'gk', $lng, $lat, 500, 'mi');
4981+
4982+
/* Test a bad COUNT argument */
4983+
foreach (Array(-1, 0, 'notanumber') as $count) {
4984+
$this->assertFalse(@$this->redis->georadius('gk', $lng, $lat, 10, 'mi', Array('count' => $count)));
4985+
}
49814986
} else {
49824987
$this->assertEquals($this->redis->georadiusbymember('gk', $city, 10, 'mi'), Array('Chico'));
49834988
$this->assertEquals($this->redis->georadiusbymember('gk', $city, 30, 'mi'), Array('Gridley','Chico'));
49844989
$this->assertEquals($this->redis->georadiusbymember('gk', $city, 50, 'km'), Array('Gridley','Chico'));
49854990
$this->assertEquals($this->redis->georadiusbymember('gk', $city, 50000, 'm'), Array('Gridley','Chico'));
49864991
$this->assertEquals($this->redis->georadiusbymember('gk', $city, 150000, 'ft'), Array('Gridley', 'Chico'));
49874992
$args = Array('georadiusbymember', 'gk', $city, 500, 'mi');
4993+
4994+
/* Test a bad COUNT argument */
4995+
foreach (Array(-1, 0, 'notanumber') as $count) {
4996+
$this->assertFalse(@$this->redis->georadiusbymember('gk', $city, 10, 'mi', Array('count' => -1)));
4997+
}
49884998
}
49894999

49905000
/* Options */

0 commit comments

Comments
 (0)