Browse files

Change getDoubleFromObject to fail on NaN.

Return an error when the resulting value is not a number (NaN). Fix
ZUNIONSTORE/ZINTERSTORE to clean up when a weight argument is not a
double value.
  • Loading branch information...
1 parent d9e28bc commit 673e1fb7e4c171f5ead560f6886e877f43730cf0 @pietern pietern committed Jul 29, 2010
Showing with 31 additions and 27 deletions.
  1. +2 −1 src/object.c
  2. +8 −11 src/t_zset.c
  3. +21 −15 tests/unit/type/zset.tcl
View
3 src/object.c
@@ -1,5 +1,6 @@
#include "redis.h"
#include <pthread.h>
+#include <math.h>
robj *createObject(int type, void *ptr) {
robj *o;
@@ -319,7 +320,7 @@ int getDoubleFromObject(robj *o, double *target) {
redisAssert(o->type == REDIS_STRING);
if (o->encoding == REDIS_ENCODING_RAW) {
value = strtod(o->ptr, &eptr);
- if (eptr[0] != '\0') return REDIS_ERR;
+ if (eptr[0] != '\0' || isnan(value)) return REDIS_ERR;
} else if (o->encoding == REDIS_ENCODING_INT) {
value = (long)o->ptr;
} else {
View
19 src/t_zset.c
@@ -327,11 +327,6 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i
zset *zs;
double *score;
- if (isnan(scoreval)) {
- addReplySds(c,sdsnew("-ERR provide score is Not A Number (nan)\r\n"));
- return;
- }
-
zsetobj = lookupKeyWrite(c->db,key);
if (zsetobj == NULL) {
zsetobj = createZsetObject();
@@ -361,7 +356,7 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i
}
if (isnan(*score)) {
addReplySds(c,
- sdsnew("-ERR resulting score is Not A Number (nan)\r\n"));
+ sdsnew("-ERR resulting score is not a number (NaN)\r\n"));
zfree(score);
/* Note that we don't need to check if the zset may be empty and
* should be removed here, as we can only obtain Nan as score if
@@ -417,15 +412,13 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i
void zaddCommand(redisClient *c) {
double scoreval;
-
- if (getDoubleFromObjectOrReply(c, c->argv[2], &scoreval, NULL) != REDIS_OK) return;
+ if (getDoubleFromObjectOrReply(c,c->argv[2],&scoreval,NULL) != REDIS_OK) return;
zaddGenericCommand(c,c->argv[1],c->argv[3],scoreval,0);
}
void zincrbyCommand(redisClient *c) {
double scoreval;
-
- if (getDoubleFromObjectOrReply(c, c->argv[2], &scoreval, NULL) != REDIS_OK) return;
+ if (getDoubleFromObjectOrReply(c,c->argv[2],&scoreval,NULL) != REDIS_OK) return;
zaddGenericCommand(c,c->argv[1],c->argv[3],scoreval,1);
}
@@ -608,8 +601,12 @@ void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
if (remaining >= (setnum + 1) && !strcasecmp(c->argv[j]->ptr,"weights")) {
j++; remaining--;
for (i = 0; i < setnum; i++, j++, remaining--) {
- if (getDoubleFromObjectOrReply(c, c->argv[j], &src[i].weight, NULL) != REDIS_OK)
+ if (getDoubleFromObjectOrReply(c,c->argv[j],&src[i].weight,
+ "weight value is not a double") != REDIS_OK)
+ {
+ zfree(src);
return;
+ }
}
} else if (remaining >= 2 && !strcasecmp(c->argv[j]->ptr,"aggregate")) {
j++; remaining--;
View
36 tests/unit/type/zset.tcl
@@ -435,6 +435,8 @@ start_server {tags {"zset"}} {
foreach cmd {ZUNIONSTORE ZINTERSTORE} {
test "$cmd with +inf/-inf scores" {
+ r del zsetinf1 zsetinf2
+
r zadd zsetinf1 +inf key
r zadd zsetinf2 +inf key
r $cmd zsetinf3 2 zsetinf1 zsetinf2
@@ -455,6 +457,16 @@ start_server {tags {"zset"}} {
r $cmd zsetinf3 2 zsetinf1 zsetinf2
assert_equal -inf [r zscore zsetinf3 key]
}
+
+ test "$cmd with NaN weights" {
+ r del zsetinf1 zsetinf2
+
+ r zadd zsetinf1 1.0 key
+ r zadd zsetinf2 1.0 key
+ assert_error "*weight value is not a double*" {
+ r $cmd zsetinf3 2 zsetinf1 zsetinf2 weights nan nan
+ }
+ }
}
tags {"slow"} {
@@ -501,22 +513,16 @@ start_server {tags {"zset"}} {
} {}
}
- test {ZSET element can't be set to nan with ZADD} {
- set e {}
- catch {r zadd myzset nan abc} e
- set _ $e
- } {*Not A Number*}
+ test {ZSET element can't be set to NaN with ZADD} {
+ assert_error "*not a double*" {r zadd myzset nan abc}
+ }
- test {ZSET element can't be set to nan with ZINCRBY} {
- set e {}
- catch {r zincrby myzset nan abc} e
- set _ $e
- } {*Not A Number*}
+ test {ZSET element can't be set to NaN with ZINCRBY} {
+ assert_error "*not a double*" {r zadd myzset nan abc}
+ }
- test {ZINCRBY calls leading to Nan are refused} {
- set e {}
+ test {ZINCRBY calls leading to NaN result in error} {
r zincrby myzset +inf abc
- catch {r zincrby myzset -inf abc} e
- set _ $e
- } {*Not A Number*}
+ assert_error "*NaN*" {r zincrby myzset -inf abc}
+ }
}

0 comments on commit 673e1fb

Please sign in to comment.