diff options
Diffstat (limited to 'examples/redis-unstable/tests/modules/crash.c')
| -rw-r--r-- | examples/redis-unstable/tests/modules/crash.c | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/examples/redis-unstable/tests/modules/crash.c b/examples/redis-unstable/tests/modules/crash.c new file mode 100644 index 0000000..c5063d0 --- /dev/null +++ b/examples/redis-unstable/tests/modules/crash.c @@ -0,0 +1,311 @@ +#include "redismodule.h" + +#include <strings.h> +#include <sys/mman.h> + +#define UNUSED(V) ((void) V) + +void assertCrash(RedisModuleInfoCtx *ctx, int for_crash_report) { + UNUSED(ctx); + UNUSED(for_crash_report); + RedisModule_Assert(0); +} + +void segfaultCrash(RedisModuleInfoCtx *ctx, int for_crash_report) { + UNUSED(ctx); + UNUSED(for_crash_report); + /* Compiler gives warnings about writing to a random address + * e.g "*((char*)-1) = 'x';". As a workaround, we map a read-only area + * and try to write there to trigger segmentation fault. */ + char *p = mmap(NULL, 4096, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + *p = 'x'; +} + +int cmd_crash(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + UNUSED(ctx); + UNUSED(argv); + UNUSED(argc); + + RedisModule_Assert(0); + return REDISMODULE_OK; +} + +int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + REDISMODULE_NOT_USED(argv); + REDISMODULE_NOT_USED(argc); + if (RedisModule_Init(ctx,"modulecrash",1,REDISMODULE_APIVER_1) + == REDISMODULE_ERR) return REDISMODULE_ERR; + + if (argc >= 1) { + if (!strcasecmp(RedisModule_StringPtrLen(argv[0], NULL), "segfault")) { + if (RedisModule_RegisterInfoFunc(ctx, segfaultCrash) == REDISMODULE_ERR) return REDISMODULE_ERR; + } else if (!strcasecmp(RedisModule_StringPtrLen(argv[0], NULL),"assert")) { + if (RedisModule_RegisterInfoFunc(ctx, assertCrash) == REDISMODULE_ERR) return REDISMODULE_ERR; + } + } + + /* Create modulecrash.xadd command which is similar to xadd command. + * It will crash in the command handler to verify we print command tokens + * when hide-user-data-from-log config is enabled */ + RedisModuleCommandInfo info = { + .version = REDISMODULE_COMMAND_INFO_VERSION, + .arity = -5, + .key_specs = (RedisModuleCommandKeySpec[]){ + { + .notes = "UPDATE instead of INSERT because of the optional trimming feature", + .flags = REDISMODULE_CMD_KEY_RW | REDISMODULE_CMD_KEY_UPDATE, + .begin_search_type = REDISMODULE_KSPEC_BS_INDEX, + .bs.index.pos = 1, + .find_keys_type = REDISMODULE_KSPEC_FK_RANGE, + .fk.range = {0,1,0} + }, + {0} + }, + .args = (RedisModuleCommandArg[]){ + { + .name = "key", + .type = REDISMODULE_ARG_TYPE_KEY, + .key_spec_index = 0 + }, + { + .name = "nomkstream", + .type = REDISMODULE_ARG_TYPE_PURE_TOKEN, + .token = "NOMKSTREAM", + .since = "6.2.0", + .flags = REDISMODULE_CMD_ARG_OPTIONAL + }, + { + .name = "trim", + .type = REDISMODULE_ARG_TYPE_BLOCK, + .flags = REDISMODULE_CMD_ARG_OPTIONAL, + .subargs = (RedisModuleCommandArg[]){ + { + .name = "strategy", + .type = REDISMODULE_ARG_TYPE_ONEOF, + .subargs = (RedisModuleCommandArg[]){ + { + .name = "maxlen", + .type = REDISMODULE_ARG_TYPE_PURE_TOKEN, + .token = "MAXLEN", + }, + { + .name = "minid", + .type = REDISMODULE_ARG_TYPE_PURE_TOKEN, + .token = "MINID", + .since = "6.2.0", + }, + {0} + } + }, + { + .name = "operator", + .type = REDISMODULE_ARG_TYPE_ONEOF, + .flags = REDISMODULE_CMD_ARG_OPTIONAL, + .subargs = (RedisModuleCommandArg[]){ + { + .name = "equal", + .type = REDISMODULE_ARG_TYPE_PURE_TOKEN, + .token = "=" + }, + { + .name = "approximately", + .type = REDISMODULE_ARG_TYPE_PURE_TOKEN, + .token = "~" + }, + {0} + } + }, + { + .name = "threshold", + .type = REDISMODULE_ARG_TYPE_STRING, + .display_text = "threshold" /* Just for coverage, doesn't have a visible effect */ + }, + { + .name = "count", + .type = REDISMODULE_ARG_TYPE_INTEGER, + .token = "LIMIT", + .since = "6.2.0", + .flags = REDISMODULE_CMD_ARG_OPTIONAL + }, + {0} + } + }, + { + .name = "id-selector", + .type = REDISMODULE_ARG_TYPE_ONEOF, + .subargs = (RedisModuleCommandArg[]){ + { + .name = "auto-id", + .type = REDISMODULE_ARG_TYPE_PURE_TOKEN, + .token = "*" + }, + { + .name = "id", + .type = REDISMODULE_ARG_TYPE_STRING, + }, + {0} + } + }, + { + .name = "data", + .type = REDISMODULE_ARG_TYPE_BLOCK, + .flags = REDISMODULE_CMD_ARG_MULTIPLE, + .subargs = (RedisModuleCommandArg[]){ + { + .name = "field", + .type = REDISMODULE_ARG_TYPE_STRING, + }, + { + .name = "value", + .type = REDISMODULE_ARG_TYPE_STRING, + }, + {0} + } + }, + {0} + } + }; + + RedisModuleCommand *cmd; + + if (RedisModule_CreateCommand(ctx,"modulecrash.xadd", cmd_crash,"write deny-oom random fast",0,0,0) == REDISMODULE_ERR) + return REDISMODULE_ERR; + cmd = RedisModule_GetCommand(ctx,"modulecrash.xadd"); + if (RedisModule_SetCommandInfo(cmd, &info) == REDISMODULE_ERR) + return REDISMODULE_ERR; + + /* Create a subcommand: modulecrash.parent sub + * It will crash in the command handler to verify we print subcommand name + * when hide-user-data-from-log config is enabled */ + RedisModuleCommandInfo subcommand_info = { + .version = REDISMODULE_COMMAND_INFO_VERSION, + .arity = -5, + .key_specs = (RedisModuleCommandKeySpec[]){ + { + .flags = REDISMODULE_CMD_KEY_RW | REDISMODULE_CMD_KEY_UPDATE, + .begin_search_type = REDISMODULE_KSPEC_BS_INDEX, + .bs.index.pos = 1, + .find_keys_type = REDISMODULE_KSPEC_FK_RANGE, + .fk.range = {0,1,0} + }, + {0} + }, + .args = (RedisModuleCommandArg[]){ + { + .name = "key", + .type = REDISMODULE_ARG_TYPE_KEY, + .key_spec_index = 0 + }, + { + .name = "token", + .type = REDISMODULE_ARG_TYPE_PURE_TOKEN, + .token = "TOKEN", + .flags = REDISMODULE_CMD_ARG_OPTIONAL + }, + { + .name = "data", + .type = REDISMODULE_ARG_TYPE_BLOCK, + .subargs = (RedisModuleCommandArg[]){ + { + .name = "field", + .type = REDISMODULE_ARG_TYPE_STRING, + }, + { + .name = "value", + .type = REDISMODULE_ARG_TYPE_STRING, + }, + {0} + } + }, + {0} + } + }; + + if (RedisModule_CreateCommand(ctx,"modulecrash.parent",NULL,"",0,0,0) == REDISMODULE_ERR) + return REDISMODULE_ERR; + + RedisModuleCommand *parent = RedisModule_GetCommand(ctx,"modulecrash.parent"); + + if (RedisModule_CreateSubcommand(parent,"subcmd",cmd_crash,"",0,0,0) == REDISMODULE_ERR) + return REDISMODULE_ERR; + + cmd = RedisModule_GetCommand(ctx,"modulecrash.parent|subcmd"); + if (RedisModule_SetCommandInfo(cmd, &subcommand_info) == REDISMODULE_ERR) + return REDISMODULE_ERR; + + /* Create modulecrash.zunion command which is similar to zunion command. + * It will crash in the command handler to verify we print command tokens + * when hide-user-data-from-log config is enabled */ + RedisModuleCommandInfo zunioninfo = { + .version = REDISMODULE_COMMAND_INFO_VERSION, + .arity = -5, + .key_specs = (RedisModuleCommandKeySpec[]){ + { + .flags = REDISMODULE_CMD_KEY_RO, + .begin_search_type = REDISMODULE_KSPEC_BS_INDEX, + .bs.index.pos = 1, + .find_keys_type = REDISMODULE_KSPEC_FK_KEYNUM, + .fk.keynum = {0,1,1} + }, + {0} + }, + .args = (RedisModuleCommandArg[]){ + { + .name = "numkeys", + .type = REDISMODULE_ARG_TYPE_INTEGER, + }, + { + .name = "key", + .type = REDISMODULE_ARG_TYPE_KEY, + .key_spec_index = 0, + .flags = REDISMODULE_CMD_ARG_MULTIPLE + }, + { + .name = "weights", + .type = REDISMODULE_ARG_TYPE_INTEGER, + .token = "WEIGHTS", + .flags = REDISMODULE_CMD_ARG_OPTIONAL | REDISMODULE_CMD_ARG_MULTIPLE + }, + { + .name = "aggregate", + .type = REDISMODULE_ARG_TYPE_ONEOF, + .token = "AGGREGATE", + .flags = REDISMODULE_CMD_ARG_OPTIONAL, + .subargs = (RedisModuleCommandArg[]){ + { + .name = "sum", + .type = REDISMODULE_ARG_TYPE_PURE_TOKEN, + .token = "sum" + }, + { + .name = "min", + .type = REDISMODULE_ARG_TYPE_PURE_TOKEN, + .token = "min" + }, + { + .name = "max", + .type = REDISMODULE_ARG_TYPE_PURE_TOKEN, + .token = "max" + }, + {0} + } + }, + { + .name = "withscores", + .type = REDISMODULE_ARG_TYPE_PURE_TOKEN, + .token = "WITHSCORES", + .flags = REDISMODULE_CMD_ARG_OPTIONAL + }, + {0} + } + }; + + if (RedisModule_CreateCommand(ctx,"modulecrash.zunion", cmd_crash,"readonly",0,0,0) == REDISMODULE_ERR) + return REDISMODULE_ERR; + cmd = RedisModule_GetCommand(ctx,"modulecrash.zunion"); + if (RedisModule_SetCommandInfo(cmd, &zunioninfo) == REDISMODULE_ERR) + return REDISMODULE_ERR; + + + return REDISMODULE_OK; +} |
