From c6375e6a60f073fab53700b83f0f140d9a27637e Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Thu, 29 Jul 2010 21:31:58 +0200 Subject: [PATCH] Fix ZUNIONSTORE/ZINTERSTORE to never store a NaN score. When +inf and -inf are added, the result is NaN. We don't want NaN scores in a sorted set, so agreed on the result of this operation being zero. Backport of d9e28bcf to 2.0.0. --- redis.c | 4 ++++ tests/unit/type/zset.tcl | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/redis.c b/redis.c index 1562a047..0e3dda11 100644 --- a/redis.c +++ b/redis.c @@ -5947,6 +5947,10 @@ static int qsortCompareZsetopsrcByCardinality(const void *s1, const void *s2) { inline static void zunionInterAggregate(double *target, double val, int aggregate) { if (aggregate == REDIS_AGGR_SUM) { *target = *target + val; + /* The result of adding two doubles is NaN when one variable + * is +inf and the other is -inf. When these numbers are added, + * we maintain the convention of the result being 0.0. */ + if (isnan(*target)) *target = 0.0; } else if (aggregate == REDIS_AGGR_MIN) { *target = val < *target ? val : *target; } else if (aggregate == REDIS_AGGR_MAX) { diff --git a/tests/unit/type/zset.tcl b/tests/unit/type/zset.tcl index 0fbe59c6..071dc2e5 100644 --- a/tests/unit/type/zset.tcl +++ b/tests/unit/type/zset.tcl @@ -417,6 +417,30 @@ start_server {tags {"zset"}} { list [r zinterstore zsetc 2 zseta zsetb aggregate max] [r zrange zsetc 0 -1 withscores] } {2 {b 2 c 3}} + foreach cmd {ZUNIONSTORE ZINTERSTORE} { + test "$cmd with +inf/-inf scores" { + r zadd zsetinf1 +inf key + r zadd zsetinf2 +inf key + r $cmd zsetinf3 2 zsetinf1 zsetinf2 + assert_equal inf [r zscore zsetinf3 key] + + r zadd zsetinf1 -inf key + r zadd zsetinf2 +inf key + r $cmd zsetinf3 2 zsetinf1 zsetinf2 + assert_equal 0 [r zscore zsetinf3 key] + + r zadd zsetinf1 +inf key + r zadd zsetinf2 -inf key + r $cmd zsetinf3 2 zsetinf1 zsetinf2 + assert_equal 0 [r zscore zsetinf3 key] + + r zadd zsetinf1 -inf key + r zadd zsetinf2 -inf key + r $cmd zsetinf3 2 zsetinf1 zsetinf2 + assert_equal -inf [r zscore zsetinf3 key] + } + } + tags {"slow"} { test {ZSETs skiplist implementation backlink consistency test} { set diff 0