"vscode:/vscode.git/clone" did not exist on "66c146592a0c0ff39570633811008cee8773233e"
Commit 673e1fb7 authored by Pieter Noordhuis's avatar Pieter Noordhuis
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.
parent d9e28bcf
#include "redis.h" #include "redis.h"
#include <pthread.h> #include <pthread.h>
#include <math.h>
robj *createObject(int type, void *ptr) { robj *createObject(int type, void *ptr) {
robj *o; robj *o;
...@@ -319,7 +320,7 @@ int getDoubleFromObject(robj *o, double *target) { ...@@ -319,7 +320,7 @@ int getDoubleFromObject(robj *o, double *target) {
redisAssert(o->type == REDIS_STRING); redisAssert(o->type == REDIS_STRING);
if (o->encoding == REDIS_ENCODING_RAW) { if (o->encoding == REDIS_ENCODING_RAW) {
value = strtod(o->ptr, &eptr); 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) { } else if (o->encoding == REDIS_ENCODING_INT) {
value = (long)o->ptr; value = (long)o->ptr;
} else { } else {
......
...@@ -327,11 +327,6 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i ...@@ -327,11 +327,6 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i
zset *zs; zset *zs;
double *score; double *score;
if (isnan(scoreval)) {
addReplySds(c,sdsnew("-ERR provide score is Not A Number (nan)\r\n"));
return;
}
zsetobj = lookupKeyWrite(c->db,key); zsetobj = lookupKeyWrite(c->db,key);
if (zsetobj == NULL) { if (zsetobj == NULL) {
zsetobj = createZsetObject(); zsetobj = createZsetObject();
...@@ -361,7 +356,7 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i ...@@ -361,7 +356,7 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i
} }
if (isnan(*score)) { if (isnan(*score)) {
addReplySds(c, 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); zfree(score);
/* Note that we don't need to check if the zset may be empty and /* 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 * 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 ...@@ -417,15 +412,13 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i
void zaddCommand(redisClient *c) { void zaddCommand(redisClient *c) {
double scoreval; 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); zaddGenericCommand(c,c->argv[1],c->argv[3],scoreval,0);
} }
void zincrbyCommand(redisClient *c) { void zincrbyCommand(redisClient *c) {
double scoreval; 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); zaddGenericCommand(c,c->argv[1],c->argv[3],scoreval,1);
} }
...@@ -608,8 +601,12 @@ void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) { ...@@ -608,8 +601,12 @@ void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
if (remaining >= (setnum + 1) && !strcasecmp(c->argv[j]->ptr,"weights")) { if (remaining >= (setnum + 1) && !strcasecmp(c->argv[j]->ptr,"weights")) {
j++; remaining--; j++; remaining--;
for (i = 0; i < setnum; i++, 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; return;
}
} }
} else if (remaining >= 2 && !strcasecmp(c->argv[j]->ptr,"aggregate")) { } else if (remaining >= 2 && !strcasecmp(c->argv[j]->ptr,"aggregate")) {
j++; remaining--; j++; remaining--;
......
...@@ -435,6 +435,8 @@ start_server {tags {"zset"}} { ...@@ -435,6 +435,8 @@ start_server {tags {"zset"}} {
foreach cmd {ZUNIONSTORE ZINTERSTORE} { foreach cmd {ZUNIONSTORE ZINTERSTORE} {
test "$cmd with +inf/-inf scores" { test "$cmd with +inf/-inf scores" {
r del zsetinf1 zsetinf2
r zadd zsetinf1 +inf key r zadd zsetinf1 +inf key
r zadd zsetinf2 +inf key r zadd zsetinf2 +inf key
r $cmd zsetinf3 2 zsetinf1 zsetinf2 r $cmd zsetinf3 2 zsetinf1 zsetinf2
...@@ -455,6 +457,16 @@ start_server {tags {"zset"}} { ...@@ -455,6 +457,16 @@ start_server {tags {"zset"}} {
r $cmd zsetinf3 2 zsetinf1 zsetinf2 r $cmd zsetinf3 2 zsetinf1 zsetinf2
assert_equal -inf [r zscore zsetinf3 key] 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"} { tags {"slow"} {
...@@ -501,22 +513,16 @@ start_server {tags {"zset"}} { ...@@ -501,22 +513,16 @@ start_server {tags {"zset"}} {
} {} } {}
} }
test {ZSET element can't be set to nan with ZADD} { test {ZSET element can't be set to NaN with ZADD} {
set e {} assert_error "*not a double*" {r zadd myzset nan abc}
catch {r zadd myzset nan abc} e }
set _ $e
} {*Not A Number*}
test {ZSET element can't be set to nan with ZINCRBY} { test {ZSET element can't be set to NaN with ZINCRBY} {
set e {} assert_error "*not a double*" {r zadd myzset nan abc}
catch {r zincrby myzset nan abc} e }
set _ $e
} {*Not A Number*}
test {ZINCRBY calls leading to Nan are refused} { test {ZINCRBY calls leading to NaN result in error} {
set e {}
r zincrby myzset +inf abc r zincrby myzset +inf abc
catch {r zincrby myzset -inf abc} e assert_error "*NaN*" {r zincrby myzset -inf abc}
set _ $e }
} {*Not A Number*}
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment