X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/91504b6cbec2f555a3aa81113372c173adadad66..1333f98dd2ff2aae4e4c2a9a43d7b83a0b1af8aa:/src/t_zset.c diff --git a/src/t_zset.c b/src/t_zset.c index f1a10378..8139b53d 100644 --- a/src/t_zset.c +++ b/src/t_zset.c @@ -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; } } @@ -435,12 +440,14 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double score, int void zaddCommand(redisClient *c) { double scoreval; if (getDoubleFromObjectOrReply(c,c->argv[2],&scoreval,NULL) != REDIS_OK) return; + c->argv[3] = tryObjectEncoding(c->argv[3]); 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; + c->argv[3] = tryObjectEncoding(c->argv[3]); zaddGenericCommand(c,c->argv[1],c->argv[3],scoreval,1); } @@ -455,6 +462,7 @@ void zremCommand(redisClient *c) { checkType(c,zsetobj,REDIS_ZSET)) return; zs = zsetobj->ptr; + c->argv[2] = tryObjectEncoding(c->argv[2]); de = dictFind(zs->dict,c->argv[2]); if (de == NULL) { addReply(c,shared.czero); @@ -481,7 +489,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 +849,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. */ @@ -993,6 +1007,7 @@ void zscoreCommand(redisClient *c) { checkType(c,o,REDIS_ZSET)) return; zs = o->ptr; + c->argv[2] = tryObjectEncoding(c->argv[2]); de = dictFind(zs->dict,c->argv[2]); if (!de) { addReply(c,shared.nullbulk); @@ -1016,6 +1031,7 @@ void zrankGenericCommand(redisClient *c, int reverse) { zs = o->ptr; zsl = zs->zsl; + c->argv[2] = tryObjectEncoding(c->argv[2]); de = dictFind(zs->dict,c->argv[2]); if (!de) { addReply(c,shared.nullbulk);