[redis]github-516 Report

1. Symptom

Wrong result. With the following commands:

sadd one 100 101 102 103
sadd two 100 200 201 202
zadd three 1 500 1 501 1 502 1 503 1 100

zinterstore to_here 3 one two three WEIGHTS 0 0 1

(integer) 0

The correct behavior should be “1”.

1.1 Severity

severe

1.2 Was there exception thrown?

No

1.2.1 Were there multiple exceptions?

No

1.3 Scope of the failure

Single client, single request.

2. How to reproduce this failure

2.0 Version

2.4.12

2.1 Configuration

Standard

2.2 Reproduction procedure

sadd one 100 101 102 103
sadd two 100 200 201 202
zadd three 1 500 1 501 1 502 1 503 1 100

zinterstore to_here 3 one two three WEIGHTS 0 0 1

(integer) 0

2.2.1 Timing order

In this order

2.2.2 Events order externally controllable? (Deterministic)

Yes

2.3 Can the logs tell how to reproduce the failure?

Client log: yes. Not from the server log.

2.4 How many machines needed?

1

3. Diagnosis procedure

3.1 Detailed Symptom (where you start)

The wrong result

3.2 Backward inference

The error log is useless from this.

4. Root cause

A stupid programming error (messed up address vs. content). The bug completely broke zuiNext() iterator, that is used in the
ZINTERSTORE and ZUNIONSTORE implementation, so those two commands are no
longer reliable starting from Redis version 2.4.12 and latest 2.6.0-RC
releases.

4.1 Category:

Semantic

5. Fix

5.1 How?

@@ -1261,10 +1261,11 @@ int zuiNext(zsetopsrc *op, zsetopval *val) {

     if (op->type == REDIS_SET) {

         iterset *it = &op->iter.set;

         if (op->encoding == REDIS_ENCODING_INTSET) {

-            int64_t ell = val->ell;

+            int64_t ell;

 

             if (!intsetGet(it->is.is,it->is.ii,&ell))

                 return 0;

+            val->ell = ell;

             val->score = 1.0;

 

             /* Move to next element. */

So this is an implementation error. The intention was to set “val->ell” from “intsetGet”, but the implementation messed up the “address” from “content”.