fix wrong data type conversion in zrangeResultBeginStore (#13148)
In `beginResultEmission`, -1 means the result length is not known in advance. But after #12185, if we pass -1 to `zrangeResultBeginStore`, it will convert to SIZE_MAX in `zsetTypeCreate` and try to `dictExpand`. Although `dictExpand` won't succeed because the size overflows, I think we'd better to avoid this wrong conversion. This bug can be triggered when the source of `zrangestore` doesn't exist or we use `zrangestore` command with `byscore` or `bylex`. The impact is that dst keys will be converted to use skiplist instead of listpack. Signed-off-by: Ping Xie <pingxie@google.com>
This commit is contained in:
parent
306ce81c10
commit
2342db3927
@ -1172,7 +1172,8 @@ unsigned long zsetLength(const robj *zobj) {
|
|||||||
* and the value len hint indicates the approximate individual size of the added elements,
|
* and the value len hint indicates the approximate individual size of the added elements,
|
||||||
* they are used to determine the initial representation.
|
* they are used to determine the initial representation.
|
||||||
*
|
*
|
||||||
* If the hints are not known, and underestimation or 0 is suitable. */
|
* If the hints are not known, and underestimation or 0 is suitable.
|
||||||
|
* We should never pass a negative value because it will convert to a very large unsigned number. */
|
||||||
robj *zsetTypeCreate(size_t size_hint, size_t val_len_hint) {
|
robj *zsetTypeCreate(size_t size_hint, size_t val_len_hint) {
|
||||||
if (size_hint <= server.zset_max_listpack_entries &&
|
if (size_hint <= server.zset_max_listpack_entries &&
|
||||||
val_len_hint <= server.zset_max_listpack_value)
|
val_len_hint <= server.zset_max_listpack_value)
|
||||||
@ -3001,7 +3002,7 @@ static void zrangeResultFinalizeClient(zrange_result_handler *handler,
|
|||||||
/* Result handler methods for storing the ZRANGESTORE to a zset. */
|
/* Result handler methods for storing the ZRANGESTORE to a zset. */
|
||||||
static void zrangeResultBeginStore(zrange_result_handler *handler, long length)
|
static void zrangeResultBeginStore(zrange_result_handler *handler, long length)
|
||||||
{
|
{
|
||||||
handler->dstobj = zsetTypeCreate(length, 0);
|
handler->dstobj = zsetTypeCreate(length >= 0 ? length : 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void zrangeResultEmitCBufferForStore(zrange_result_handler *handler,
|
static void zrangeResultEmitCBufferForStore(zrange_result_handler *handler,
|
||||||
|
@ -2239,12 +2239,18 @@ start_server {tags {"zset"}} {
|
|||||||
} {b 2 c 3}
|
} {b 2 c 3}
|
||||||
|
|
||||||
test {ZRANGESTORE BYLEX} {
|
test {ZRANGESTORE BYLEX} {
|
||||||
|
set res [r zrangestore z3{t} z1{t} \[b \[c BYLEX]
|
||||||
|
assert_equal $res 2
|
||||||
|
assert_encoding listpack z3{t}
|
||||||
set res [r zrangestore z2{t} z1{t} \[b \[c BYLEX]
|
set res [r zrangestore z2{t} z1{t} \[b \[c BYLEX]
|
||||||
assert_equal $res 2
|
assert_equal $res 2
|
||||||
r zrange z2{t} 0 -1 withscores
|
r zrange z2{t} 0 -1 withscores
|
||||||
} {b 2 c 3}
|
} {b 2 c 3}
|
||||||
|
|
||||||
test {ZRANGESTORE BYSCORE} {
|
test {ZRANGESTORE BYSCORE} {
|
||||||
|
set res [r zrangestore z4{t} z1{t} 1 2 BYSCORE]
|
||||||
|
assert_equal $res 2
|
||||||
|
assert_encoding listpack z4{t}
|
||||||
set res [r zrangestore z2{t} z1{t} 1 2 BYSCORE]
|
set res [r zrangestore z2{t} z1{t} 1 2 BYSCORE]
|
||||||
assert_equal $res 2
|
assert_equal $res 2
|
||||||
r zrange z2{t} 0 -1 withscores
|
r zrange z2{t} 0 -1 withscores
|
||||||
|
Loading…
x
Reference in New Issue
Block a user