]> git.saurik.com Git - redis.git/commitdiff
Return error when min and/or max in the sorted set range spec is not a double
authorPieter Noordhuis <pcnoordhuis@gmail.com>
Wed, 13 Oct 2010 19:58:21 +0000 (21:58 +0200)
committerPieter Noordhuis <pcnoordhuis@gmail.com>
Wed, 13 Oct 2010 19:59:24 +0000 (21:59 +0200)
src/t_zset.c
tests/unit/type/zset.tcl

index f1a10378cbda8e596468404fae0eb9da280d6542..d45e93691bb01b3fa8a88fddab3e643f0758ba0a 100644 (file)
@@ -307,7 +307,8 @@ zskiplistNode* zslistTypeGetElementByRank(zskiplist *zsl, unsigned long rank) {
 }
 
 /* Populate the rangespec according to the objects min and max. */
-int zslParseRange(robj *min, robj *max, zrangespec *spec) {
+static int zslParseRange(robj *min, robj *max, zrangespec *spec) {
+    char *eptr;
     spec->minex = spec->maxex = 0;
 
     /* Parse the min-max interval. If one of the values is prefixed
@@ -318,20 +319,24 @@ int zslParseRange(robj *min, robj *max, zrangespec *spec) {
         spec->min = (long)min->ptr;
     } else {
         if (((char*)min->ptr)[0] == '(') {
-            spec->min = strtod((char*)min->ptr+1,NULL);
+            spec->min = strtod((char*)min->ptr+1,&eptr);
+            if (eptr[0] != '\0' || isnan(spec->min)) return REDIS_ERR;
             spec->minex = 1;
         } else {
-            spec->min = strtod((char*)min->ptr,NULL);
+            spec->min = strtod((char*)min->ptr,&eptr);
+            if (eptr[0] != '\0' || isnan(spec->min)) return REDIS_ERR;
         }
     }
     if (max->encoding == REDIS_ENCODING_INT) {
         spec->max = (long)max->ptr;
     } else {
         if (((char*)max->ptr)[0] == '(') {
-            spec->max = strtod((char*)max->ptr+1,NULL);
+            spec->max = strtod((char*)max->ptr+1,&eptr);
+            if (eptr[0] != '\0' || isnan(spec->max)) return REDIS_ERR;
             spec->maxex = 1;
         } else {
-            spec->max = strtod((char*)max->ptr,NULL);
+            spec->max = strtod((char*)max->ptr,&eptr);
+            if (eptr[0] != '\0' || isnan(spec->max)) return REDIS_ERR;
         }
     }
 
@@ -481,7 +486,10 @@ void zremrangebyscoreCommand(redisClient *c) {
     zset *zs;
 
     /* Parse the range arguments. */
-    zslParseRange(c->argv[2],c->argv[3],&range);
+    if (zslParseRange(c->argv[2],c->argv[3],&range) != REDIS_OK) {
+        addReplyError(c,"min or max is not a double");
+        return;
+    }
 
     if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL ||
         checkType(c,o,REDIS_ZSET)) return;
@@ -838,7 +846,10 @@ void genericZrangebyscoreCommand(redisClient *c, int reverse, int justcount) {
     void *replylen = NULL;
 
     /* Parse the range arguments. */
-    zslParseRange(c->argv[2],c->argv[3],&range);
+    if (zslParseRange(c->argv[2],c->argv[3],&range) != REDIS_OK) {
+        addReplyError(c,"min or max is not a double");
+        return;
+    }
 
     /* Parse optional extra arguments. Note that ZCOUNT will exactly have
      * 4 arguments, so we'll never enter the following code path. */
index 47c056073bcce9e9d2171b089f091619c6c9f1fe..6b8fc54ae3af6232ae6f850bdec30893fb718f6c 100644 (file)
@@ -253,6 +253,12 @@ start_server {tags {"zset"}} {
         assert_equal {d 3 c 2} [r zrevrangebyscore zset 5 2 LIMIT 2 3 WITHSCORES]
     }
 
+    test "ZRANGEBYSCORE with non-value min or max" {
+        assert_error "*not a double*" {r zrangebyscore fooz str 1}
+        assert_error "*not a double*" {r zrangebyscore fooz 1 str}
+        assert_error "*not a double*" {r zrangebyscore fooz 1 NaN}
+    }
+
     tags {"slow"} {
         test {ZRANGEBYSCORE fuzzy test, 100 ranges in 1000 elements sorted set} {
             set err {}
@@ -386,6 +392,12 @@ start_server {tags {"zset"}} {
         assert_equal {a e} [r zrange zset 0 -1]
     }
 
+    test "ZREMRANGEBYSCORE with non-value min or max" {
+        assert_error "*not a double*" {r zremrangebyscore fooz str 1}
+        assert_error "*not a double*" {r zremrangebyscore fooz 1 str}
+        assert_error "*not a double*" {r zremrangebyscore fooz 1 NaN}
+    }
+
     test "ZREMRANGEBYRANK basics" {
         proc remrangebyrank {min max} {
             create_zset zset {1 a 2 b 3 c 4 d 5 e}