From 004efaf015bc0379ceb62846a5e06b5c0d598d3f Mon Sep 17 00:00:00 2001 From: Tim Wong Date: Wed, 9 Aug 2017 17:10:04 -0700 Subject: [PATCH] ZUNIONSTORE overwrites a key after potentially reading it. --- cmd_sorted_set.go | 10 +++++++++- cmd_sorted_set_test.go | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/cmd_sorted_set.go b/cmd_sorted_set.go index 564b9e25..8a89ca82 100644 --- a/cmd_sorted_set.go +++ b/cmd_sorted_set.go @@ -1153,7 +1153,15 @@ func (m *Miniredis) cmdZunionstore(c *server.Peer, cmd string, args []string) { withTx(m, c, func(c *server.Peer, ctx *connCtx) { db := m.db(ctx.selectedDB) - db.del(destination, true) + deleteDest := true + for _, key := range keys { + if destination == key { + deleteDest = false + } + } + if deleteDest { + db.del(destination, true) + } sset := sortedSet{} for i, key := range keys { diff --git a/cmd_sorted_set_test.go b/cmd_sorted_set_test.go index 8211d833..7bbb6325 100644 --- a/cmd_sorted_set_test.go +++ b/cmd_sorted_set_test.go @@ -1106,6 +1106,20 @@ func TestZunionstore(t *testing.T) { equals(t, map[string]float64{"field1": 2, "field2": 4}, ss) } + // Merge destination with itself. + { + s.ZAdd("h3", 1.0, "field1") + s.ZAdd("h3", 3.0, "field3") + + res, err := redis.Int(c.Do("ZUNIONSTORE", "h3", 2, "h1", "h3")) + ok(t, err) + equals(t, 3, res) + + ss, err := s.SortedSet("h3") + ok(t, err) + equals(t, map[string]float64{"field1": 2, "field2": 2, "field3": 3}, ss) + } + // WEIGHTS { res, err := redis.Int(c.Do("ZUNIONSTORE", "weighted", 2, "h1", "h2", "WeIgHtS", "4.5", "12"))