summaryrefslogtreecommitdiff
path: root/tests/modules
diff options
context:
space:
mode:
authorsundb <sundbcn@gmail.com>2022-10-23 01:36:50 +0800
committerGitHub <noreply@github.com>2022-10-22 20:36:50 +0300
commit6dd213558b0f77e2233743718e23556fb06a557e (patch)
treef05ba2f9cc9d375a2db99b0b26f456186dee0899 /tests/modules
parent6debeb3779fada89c82c1ffad3cf98fa48aa3b5d (diff)
downloadredis-6dd213558b0f77e2233743718e23556fb06a557e.tar.gz
Fix crash due to to reuse iterator entry after list deletion in module (#11383)
In the module, we will reuse the list iterator entry for RM_ListDelete, but `listTypeDelete` will only update `quicklistEntry->zi` but not `quicklistEntry->node`, which will result in `quicklistEntry->node` pointing to a freed memory address if the quicklist node is deleted. This PR sync `key->u.list.index` and `key->u.list.entry` to list iterator after `RM_ListDelete`. This PR also optimizes the release code of the original list iterator. Co-authored-by: Viktor Söderqvist <viktor@zuiderkwast.se>
Diffstat (limited to 'tests/modules')
-rw-r--r--tests/modules/list.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/tests/modules/list.c b/tests/modules/list.c
index 727b05d6f..401b2d802 100644
--- a/tests/modules/list.c
+++ b/tests/modules/list.c
@@ -50,7 +50,8 @@ int list_getall(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
* The number of occurrences of "i" and "r" in cmdstr) should correspond to the
* number of args after cmdstr.
*
- * The reply is the number of edits (inserts + replaces + deletes) performed.
+ * Reply with a RESP3 Map, containing the number of edits (inserts, replaces, deletes)
+ * performed, as well as the last index and the entry it points to.
*/
int list_edit(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (argc < 3) return RedisModule_WrongArity(ctx);
@@ -92,7 +93,7 @@ int list_edit(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
}
/* Iterate over the chars in cmdstr (edit instructions) */
- long long num_edits = 0;
+ long long num_inserts = 0, num_deletes = 0, num_replaces = 0;
long index = reverse ? -1 : 0;
RedisModuleString *value;
@@ -102,17 +103,17 @@ int list_edit(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
value = argv[argpos++];
assert(RedisModule_ListInsert(key, index, value) == REDISMODULE_OK);
index += reverse ? -1 : 1;
- num_edits++;
+ num_inserts++;
break;
case 'd': /* delete */
assert(RedisModule_ListDelete(key, index) == REDISMODULE_OK);
- num_edits++;
+ num_deletes++;
break;
case 'r': /* replace */
value = argv[argpos++];
assert(RedisModule_ListSet(key, index, value) == REDISMODULE_OK);
index += reverse ? -1 : 1;
- num_edits++;
+ num_replaces++;
break;
case 'k': /* keep */
index += reverse ? -1 : 1;
@@ -120,7 +121,22 @@ int list_edit(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
}
}
- RedisModule_ReplyWithLongLong(ctx, num_edits);
+ RedisModuleString *v = RedisModule_ListGet(key, index);
+ RedisModule_ReplyWithMap(ctx, v ? 5 : 4);
+ RedisModule_ReplyWithCString(ctx, "i");
+ RedisModule_ReplyWithLongLong(ctx, num_inserts);
+ RedisModule_ReplyWithCString(ctx, "d");
+ RedisModule_ReplyWithLongLong(ctx, num_deletes);
+ RedisModule_ReplyWithCString(ctx, "r");
+ RedisModule_ReplyWithLongLong(ctx, num_replaces);
+ RedisModule_ReplyWithCString(ctx, "index");
+ RedisModule_ReplyWithLongLong(ctx, index);
+ if (v) {
+ RedisModule_ReplyWithCString(ctx, "entry");
+ RedisModule_ReplyWithString(ctx, v);
+ RedisModule_FreeString(ctx, v);
+ }
+
RedisModule_CloseKey(key);
return REDISMODULE_OK;
}