diff --git a/src/db.c b/src/db.c index 1c8557af9..fa41cc9dc 100644 --- a/src/db.c +++ b/src/db.c @@ -1299,10 +1299,14 @@ void scanGenericCommand(client *c, robj *o, unsigned long long cursor) { addReplyArrayLen(c, 2); addReplyBulkLongLong(c,cursor); + unsigned long long idx = 0; addReplyArrayLen(c, listLength(keys)); while ((node = listFirst(keys)) != NULL) { void *key = listNodeValue(node); - addReplyBulkCBuffer(c, key, (isKeysHfield) ? mstrlen(key) : sdslen(key)); + /* For HSCAN, list will contain keys value pairs unless no_values arg + * was given. We should call mstrlen for the keys only. */ + int hfieldkey = isKeysHfield && (no_values || (idx++ % 2 == 0)); + addReplyBulkCBuffer(c, key, hfieldkey ? mstrlen(key) : sdslen(key)); listDelNode(keys, node); } diff --git a/tests/unit/scan.tcl b/tests/unit/scan.tcl index d980a52ad..8ab14d3b1 100644 --- a/tests/unit/scan.tcl +++ b/tests/unit/scan.tcl @@ -277,6 +277,32 @@ proc test_scan {type} { set res [r hscan hash 0 count 1000 novalues] assert_equal [lsort $keys2] [lsort [lindex $res 1]] } + + test "{$type} HSCAN with large value $enc" { + r del hash + + if {$enc eq {listpack}} { + set count 60 + } else { + set count 170 + } + + set val1 [string repeat "1" $count] + r hset hash $val1 $val1 + + set val2 [string repeat "2" $count] + r hset hash $val2 $val2 + + set res [lsort [lindex [r hscan hash 0] 1]] + assert_equal $val1 [lindex $res 0] + assert_equal $val1 [lindex $res 1] + assert_equal $val2 [lindex $res 2] + assert_equal $val2 [lindex $res 3] + + set res [lsort [lindex [r hscan hash 0 novalues] 1]] + assert_equal $val1 [lindex $res 0] + assert_equal $val2 [lindex $res 1] + } } foreach enc {listpack skiplist} {