mirror of https://mirror.osredm.com/root/redis.git
Fix crash in RM_ScanKey() when used with hexpire (#13320)
RM_ScanKey() was overlooked while introducing hash field expiration. An assert is triggered when it is called on a hash key with OBJ_ENCODING_LISTPACK_EX encoding. I've changed to code to handle listpackex encoding properly.
This commit is contained in:
parent
56169112e3
commit
44352beefa
16
src/module.c
16
src/module.c
|
@ -11188,22 +11188,32 @@ int RM_ScanKey(RedisModuleKey *key, RedisModuleScanCursor *cursor, RedisModuleSc
|
||||||
cursor->done = 1;
|
cursor->done = 1;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else if (o->type == OBJ_ZSET || o->type == OBJ_HASH) {
|
} else if (o->type == OBJ_ZSET || o->type == OBJ_HASH) {
|
||||||
unsigned char *p = lpSeek(o->ptr,0);
|
unsigned char *lp, *p;
|
||||||
unsigned char *vstr;
|
unsigned char *vstr;
|
||||||
unsigned int vlen;
|
unsigned int vlen;
|
||||||
long long vll;
|
long long vll;
|
||||||
|
|
||||||
|
if (o->type == OBJ_HASH)
|
||||||
|
lp = hashTypeListpackGetLp(o);
|
||||||
|
else
|
||||||
|
lp = o->ptr;
|
||||||
|
|
||||||
|
p = lpSeek(lp,0);
|
||||||
while(p) {
|
while(p) {
|
||||||
vstr = lpGetValue(p,&vlen,&vll);
|
vstr = lpGetValue(p,&vlen,&vll);
|
||||||
robj *field = (vstr != NULL) ?
|
robj *field = (vstr != NULL) ?
|
||||||
createStringObject((char*)vstr,vlen) :
|
createStringObject((char*)vstr,vlen) :
|
||||||
createStringObjectFromLongLongWithSds(vll);
|
createStringObjectFromLongLongWithSds(vll);
|
||||||
p = lpNext(o->ptr,p);
|
p = lpNext(lp,p);
|
||||||
vstr = lpGetValue(p,&vlen,&vll);
|
vstr = lpGetValue(p,&vlen,&vll);
|
||||||
robj *value = (vstr != NULL) ?
|
robj *value = (vstr != NULL) ?
|
||||||
createStringObject((char*)vstr,vlen) :
|
createStringObject((char*)vstr,vlen) :
|
||||||
createStringObjectFromLongLongWithSds(vll);
|
createStringObjectFromLongLongWithSds(vll);
|
||||||
fn(key, field, value, privdata);
|
fn(key, field, value, privdata);
|
||||||
p = lpNext(o->ptr,p);
|
p = lpNext(lp,p);
|
||||||
|
if (o->type == OBJ_HASH && o->encoding == OBJ_ENCODING_LISTPACK_EX)
|
||||||
|
p = lpNext(lp, p); /* Skip expire time */
|
||||||
|
|
||||||
decrRefCount(field);
|
decrRefCount(field);
|
||||||
decrRefCount(value);
|
decrRefCount(value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,14 @@ start_server {tags {"modules"}} {
|
||||||
lsort [r scan.scan_key hh1]
|
lsort [r scan.scan_key hh1]
|
||||||
} {{f1 1}}
|
} {{f1 1}}
|
||||||
|
|
||||||
|
test {Module scan hash listpack with hexpire} {
|
||||||
|
r hmset hh f1 v1 f2 v2
|
||||||
|
r hexpire hh 100000 fields 1 f1
|
||||||
|
assert_range [r httl hh fields 1 f1] 10000 100000
|
||||||
|
assert_encoding listpackex hh
|
||||||
|
lsort [r scan.scan_key hh]
|
||||||
|
} {{f1 v1} {f2 v2}}
|
||||||
|
|
||||||
test {Module scan hash dict} {
|
test {Module scan hash dict} {
|
||||||
r config set hash-max-ziplist-entries 2
|
r config set hash-max-ziplist-entries 2
|
||||||
r hmset hh f3 v3
|
r hmset hh f3 v3
|
||||||
|
@ -31,6 +39,16 @@ start_server {tags {"modules"}} {
|
||||||
lsort [r scan.scan_key hh]
|
lsort [r scan.scan_key hh]
|
||||||
} {{f1 v1} {f2 v2} {f3 v3}}
|
} {{f1 v1} {f2 v2} {f3 v3}}
|
||||||
|
|
||||||
|
test {Module scan hash dict with hexpire} {
|
||||||
|
r config set hash-max-listpack-entries 1
|
||||||
|
r del hh
|
||||||
|
r hmset hh f1 v1 f2 v2 f3 v3
|
||||||
|
r hexpire hh 100000 fields 1 f2
|
||||||
|
assert_range [r httl hh fields 1 f2] 10000 100000
|
||||||
|
assert_encoding hashtable hh
|
||||||
|
lsort [r scan.scan_key hh]
|
||||||
|
} {{f1 v1} {f2 v2} {f3 v3}}
|
||||||
|
|
||||||
test {Module scan zset listpack} {
|
test {Module scan zset listpack} {
|
||||||
r zadd zz 1 f1 2 f2
|
r zadd zz 1 f1 2 f2
|
||||||
assert_encoding listpack zz
|
assert_encoding listpack zz
|
||||||
|
|
Loading…
Reference in New Issue