summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Noordhuis <pcnoordhuis@gmail.com>2010-09-03 11:52:15 +0200
committerPieter Noordhuis <pcnoordhuis@gmail.com>2010-09-03 11:53:53 +0200
commit47ae4b6a17f0423ea4bf6984cc5879f1506b71e9 (patch)
treec5d5b3cc8a1de5b876f5c8903816c264dfab3182
parent4212dd540255ef13e5358fc3de9a658b7c2dfc24 (diff)
downloadredis-47ae4b6a17f0423ea4bf6984cc5879f1506b71e9.tar.gz
Verify that the blocking pop timeout value is a non-negative integer
Backport of 94364d5 to 2.0.0.
-rw-r--r--redis.c13
-rw-r--r--tests/unit/type/list.tcl22
2 files changed, 34 insertions, 1 deletions
diff --git a/redis.c b/redis.c
index 59f84f17d..ed22d6342 100644
--- a/redis.c
+++ b/redis.c
@@ -7710,9 +7710,20 @@ static int handleClientsWaitingListPush(redisClient *c, robj *key, robj *ele) {
/* Blocking RPOP/LPOP */
static void blockingPopGenericCommand(redisClient *c, int where) {
robj *o;
+ long long lltimeout;
time_t timeout;
int j;
+ /* Make sure timeout is an integer value */
+ if (getLongLongFromObjectOrReply(c,c->argv[c->argc-1],&lltimeout,
+ "timeout is not an integer") != REDIS_OK) return;
+
+ /* Make sure the timeout is not negative */
+ if (lltimeout < 0) {
+ addReplySds(c,sdsnew("-ERR timeout is negative\r\n"));
+ return;
+ }
+
for (j = 1; j < c->argc-1; j++) {
o = lookupKeyWrite(c->db,c->argv[j]);
if (o != NULL) {
@@ -7761,7 +7772,7 @@ static void blockingPopGenericCommand(redisClient *c, int where) {
}
/* If the list is empty or the key does not exists we must block */
- timeout = strtol(c->argv[c->argc-1]->ptr,NULL,10);
+ timeout = lltimeout;
if (timeout > 0) timeout += time(NULL);
blockForKeys(c,c->argv+1,c->argc-2,timeout);
}
diff --git a/tests/unit/type/list.tcl b/tests/unit/type/list.tcl
index 8c1b0b417..e0089bf36 100644
--- a/tests/unit/type/list.tcl
+++ b/tests/unit/type/list.tcl
@@ -83,6 +83,28 @@ start_server {tags {"list"}} {
assert_equal 0 [r exists blist1]
}
+ test "$pop: with negative timeout" {
+ set rd [redis_deferring_client]
+ $rd $pop blist1 -1
+ assert_error "ERR*is negative*" {$rd read}
+ }
+
+ test "$pop: with non-integer timeout" {
+ set rd [redis_deferring_client]
+ $rd $pop blist1 1.1
+ assert_error "ERR*not an integer*" {$rd read}
+ }
+
+ test "$pop: with zero timeout should block indefinitely" {
+ # To test this, use a timeout of 0 and wait a second.
+ # The blocking pop should still be waiting for a push.
+ set rd [redis_deferring_client]
+ $rd $pop blist1 0
+ after 1000
+ r rpush blist1 foo
+ assert_equal {blist1 foo} [$rd read]
+ }
+
test "$pop: second argument is not a list" {
set rd [redis_deferring_client]
r del blist1 blist2