Commit d93f9a86 authored by antirez's avatar antirez
Browse files

string to number API is now more strict not accepting spaces before or after...

string to number API is now more strict not accepting spaces before or after the number. A few tests converted to match the new error messages using the word float instead of double.
parent 5244d6e5
#include "redis.h" #include "redis.h"
#include <math.h> #include <math.h>
#include <ctype.h>
robj *createObject(int type, void *ptr) { robj *createObject(int type, void *ptr) {
robj *o = zmalloc(sizeof(*o)); robj *o = zmalloc(sizeof(*o));
...@@ -367,7 +368,8 @@ int getDoubleFromObject(robj *o, double *target) { ...@@ -367,7 +368,8 @@ int getDoubleFromObject(robj *o, double *target) {
if (o->encoding == REDIS_ENCODING_RAW) { if (o->encoding == REDIS_ENCODING_RAW) {
errno = 0; errno = 0;
value = strtod(o->ptr, &eptr); value = strtod(o->ptr, &eptr);
if (eptr[0] != '\0' || errno == ERANGE || isnan(value)) if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' ||
errno == ERANGE || isnan(value))
return REDIS_ERR; 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;
...@@ -375,7 +377,6 @@ int getDoubleFromObject(robj *o, double *target) { ...@@ -375,7 +377,6 @@ int getDoubleFromObject(robj *o, double *target) {
redisPanic("Unknown string encoding"); redisPanic("Unknown string encoding");
} }
} }
*target = value; *target = value;
return REDIS_OK; return REDIS_OK;
} }
...@@ -390,7 +391,6 @@ int getDoubleFromObjectOrReply(redisClient *c, robj *o, double *target, const ch ...@@ -390,7 +391,6 @@ int getDoubleFromObjectOrReply(redisClient *c, robj *o, double *target, const ch
} }
return REDIS_ERR; return REDIS_ERR;
} }
*target = value; *target = value;
return REDIS_OK; return REDIS_OK;
} }
...@@ -406,7 +406,8 @@ int getLongDoubleFromObject(robj *o, long double *target) { ...@@ -406,7 +406,8 @@ int getLongDoubleFromObject(robj *o, long double *target) {
if (o->encoding == REDIS_ENCODING_RAW) { if (o->encoding == REDIS_ENCODING_RAW) {
errno = 0; errno = 0;
value = strtold(o->ptr, &eptr); value = strtold(o->ptr, &eptr);
if (eptr[0] != '\0' || errno == ERANGE || isnan(value)) if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' ||
errno == ERANGE || isnan(value))
return REDIS_ERR; 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;
...@@ -428,7 +429,6 @@ int getLongDoubleFromObjectOrReply(redisClient *c, robj *o, long double *target, ...@@ -428,7 +429,6 @@ int getLongDoubleFromObjectOrReply(redisClient *c, robj *o, long double *target,
} }
return REDIS_ERR; return REDIS_ERR;
} }
*target = value; *target = value;
return REDIS_OK; return REDIS_OK;
} }
...@@ -442,9 +442,10 @@ int getLongLongFromObject(robj *o, long long *target) { ...@@ -442,9 +442,10 @@ int getLongLongFromObject(robj *o, long long *target) {
} else { } else {
redisAssertWithInfo(NULL,o,o->type == REDIS_STRING); redisAssertWithInfo(NULL,o,o->type == REDIS_STRING);
if (o->encoding == REDIS_ENCODING_RAW) { if (o->encoding == REDIS_ENCODING_RAW) {
errno = 0;
value = strtoll(o->ptr, &eptr, 10); value = strtoll(o->ptr, &eptr, 10);
if (eptr[0] != '\0') return REDIS_ERR; if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' ||
if (errno == ERANGE && (value == LLONG_MIN || value == LLONG_MAX)) errno == ERANGE)
return REDIS_ERR; 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;
...@@ -452,7 +453,6 @@ int getLongLongFromObject(robj *o, long long *target) { ...@@ -452,7 +453,6 @@ int getLongLongFromObject(robj *o, long long *target) {
redisPanic("Unknown string encoding"); redisPanic("Unknown string encoding");
} }
} }
if (target) *target = value; if (target) *target = value;
return REDIS_OK; return REDIS_OK;
} }
...@@ -467,7 +467,6 @@ int getLongLongFromObjectOrReply(redisClient *c, robj *o, long long *target, con ...@@ -467,7 +467,6 @@ int getLongLongFromObjectOrReply(redisClient *c, robj *o, long long *target, con
} }
return REDIS_ERR; return REDIS_ERR;
} }
*target = value; *target = value;
return REDIS_OK; return REDIS_OK;
} }
...@@ -484,7 +483,6 @@ int getLongFromObjectOrReply(redisClient *c, robj *o, long *target, const char * ...@@ -484,7 +483,6 @@ int getLongFromObjectOrReply(redisClient *c, robj *o, long *target, const char *
} }
return REDIS_ERR; return REDIS_ERR;
} }
*target = value; *target = value;
return REDIS_OK; return REDIS_OK;
} }
......
...@@ -1018,7 +1018,7 @@ void zremrangebyscoreCommand(redisClient *c) { ...@@ -1018,7 +1018,7 @@ void zremrangebyscoreCommand(redisClient *c) {
/* Parse the range arguments. */ /* Parse the range arguments. */
if (zslParseRange(c->argv[2],c->argv[3],&range) != REDIS_OK) { if (zslParseRange(c->argv[2],c->argv[3],&range) != REDIS_OK) {
addReplyError(c,"min or max is not a double"); addReplyError(c,"min or max is not a float");
return; return;
} }
...@@ -1493,7 +1493,7 @@ void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) { ...@@ -1493,7 +1493,7 @@ void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
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, if (getDoubleFromObjectOrReply(c,c->argv[j],&src[i].weight,
"weight value is not a double") != REDIS_OK) "weight value is not a float") != REDIS_OK)
{ {
zfree(src); zfree(src);
return; return;
...@@ -1777,7 +1777,7 @@ void genericZrangebyscoreCommand(redisClient *c, int reverse) { ...@@ -1777,7 +1777,7 @@ void genericZrangebyscoreCommand(redisClient *c, int reverse) {
} }
if (zslParseRange(c->argv[minidx],c->argv[maxidx],&range) != REDIS_OK) { if (zslParseRange(c->argv[minidx],c->argv[maxidx],&range) != REDIS_OK) {
addReplyError(c,"min or max is not a double"); addReplyError(c,"min or max is not a float");
return; return;
} }
...@@ -1959,7 +1959,7 @@ void zcountCommand(redisClient *c) { ...@@ -1959,7 +1959,7 @@ void zcountCommand(redisClient *c) {
/* Parse the range arguments */ /* Parse the range arguments */
if (zslParseRange(c->argv[2],c->argv[3],&range) != REDIS_OK) { if (zslParseRange(c->argv[2],c->argv[3],&range) != REDIS_OK) {
addReplyError(c,"min or max is not a double"); addReplyError(c,"min or max is not a float");
return; return;
} }
......
...@@ -36,11 +36,11 @@ start_server {tags {"zset"}} { ...@@ -36,11 +36,11 @@ start_server {tags {"zset"}} {
} }
test "ZSET element can't be set to NaN with ZADD - $encoding" { test "ZSET element can't be set to NaN with ZADD - $encoding" {
assert_error "*not a double*" {r zadd myzset nan abc} assert_error "*not*float*" {r zadd myzset nan abc}
} }
test "ZSET element can't be set to NaN with ZINCRBY" { test "ZSET element can't be set to NaN with ZINCRBY" {
assert_error "*not a double*" {r zadd myzset nan abc} assert_error "*not*float*" {r zadd myzset nan abc}
} }
test "ZINCRBY calls leading to NaN result in error" { test "ZINCRBY calls leading to NaN result in error" {
...@@ -60,7 +60,7 @@ start_server {tags {"zset"}} { ...@@ -60,7 +60,7 @@ start_server {tags {"zset"}} {
test {ZADD - Variadic version does not add nothing on single parsing err} { test {ZADD - Variadic version does not add nothing on single parsing err} {
r del myzset r del myzset
catch {r zadd myzset 10 a 20 b 30.badscore c} e catch {r zadd myzset 10 a 20 b 30.badscore c} e
assert_match {*ERR*not*double*} $e assert_match {*ERR*not*float*} $e
r exists myzset r exists myzset
} {0} } {0}
...@@ -291,9 +291,9 @@ start_server {tags {"zset"}} { ...@@ -291,9 +291,9 @@ start_server {tags {"zset"}} {
} }
test "ZRANGEBYSCORE with non-value min or max" { test "ZRANGEBYSCORE with non-value min or max" {
assert_error "*not a double*" {r zrangebyscore fooz str 1} assert_error "*not*float*" {r zrangebyscore fooz str 1}
assert_error "*not a double*" {r zrangebyscore fooz 1 str} assert_error "*not*float*" {r zrangebyscore fooz 1 str}
assert_error "*not a double*" {r zrangebyscore fooz 1 NaN} assert_error "*not*float*" {r zrangebyscore fooz 1 NaN}
} }
test "ZREMRANGEBYSCORE basics" { test "ZREMRANGEBYSCORE basics" {
...@@ -353,9 +353,9 @@ start_server {tags {"zset"}} { ...@@ -353,9 +353,9 @@ start_server {tags {"zset"}} {
} }
test "ZREMRANGEBYSCORE with non-value min or max" { test "ZREMRANGEBYSCORE with non-value min or max" {
assert_error "*not a double*" {r zremrangebyscore fooz str 1} assert_error "*not*float*" {r zremrangebyscore fooz str 1}
assert_error "*not a double*" {r zremrangebyscore fooz 1 str} assert_error "*not*float*" {r zremrangebyscore fooz 1 str}
assert_error "*not a double*" {r zremrangebyscore fooz 1 NaN} assert_error "*not*float*" {r zremrangebyscore fooz 1 NaN}
} }
test "ZREMRANGEBYRANK basics" { test "ZREMRANGEBYRANK basics" {
...@@ -501,7 +501,7 @@ start_server {tags {"zset"}} { ...@@ -501,7 +501,7 @@ start_server {tags {"zset"}} {
r zadd zsetinf1 1.0 key r zadd zsetinf1 1.0 key
r zadd zsetinf2 1.0 key r zadd zsetinf2 1.0 key
assert_error "*weight value is not a double*" { assert_error "*weight*not*float*" {
r $cmd zsetinf3 2 zsetinf1 zsetinf2 weights nan nan r $cmd zsetinf3 2 zsetinf1 zsetinf2 weights nan nan
} }
} }
......
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