From d46ef88671e27128704a0de8d3310049c41bee83 Mon Sep 17 00:00:00 2001 From: guybe7 Date: Wed, 21 Jun 2023 11:48:13 +0200 Subject: [PATCH] Improve moduleBlockClient timeout overflow handling (#12174) Continuation of https://github.com/redis/redis/pull/11338 avoid overflow adding input timeout to "now" in moduleBlockClient. --- src/module.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/module.c b/src/module.c index e41b275c2..b50c316a3 100644 --- a/src/module.c +++ b/src/module.c @@ -7677,7 +7677,6 @@ RedisModuleBlockedClient *moduleBlockClient(RedisModuleCtx *ctx, RedisModuleCmdF * commands from Lua or MULTI. We actually create an already aborted * (client set to NULL) blocked client handle, and actually reply with * an error. */ - mstime_t timeout = timeout_ms ? (mstime()+timeout_ms) : 0; bc->client = (islua || ismulti) ? NULL : c; bc->module = ctx->module; bc->reply_callback = reply_callback; @@ -7695,7 +7694,17 @@ RedisModuleBlockedClient *moduleBlockClient(RedisModuleCtx *ctx, RedisModuleCmdF bc->unblocked = 0; bc->background_timer = 0; bc->background_duration = 0; - c->bstate.timeout = timeout; + + c->bstate.timeout = 0; + if (timeout_ms) { + mstime_t now = mstime(); + if (timeout_ms > LLONG_MAX - now) { + c->bstate.module_blocked_handle = NULL; + addReplyError(c, "timeout is out of range"); /* 'timeout_ms+now' would overflow */ + return bc; + } + c->bstate.timeout = timeout_ms + now; + } if (islua || ismulti) { c->bstate.module_blocked_handle = NULL; @@ -7705,13 +7714,12 @@ RedisModuleBlockedClient *moduleBlockClient(RedisModuleCtx *ctx, RedisModuleCmdF } else if (ctx->flags & REDISMODULE_CTX_BLOCKED_REPLY) { c->bstate.module_blocked_handle = NULL; addReplyError(c, "Blocking module command called from a Reply callback context"); - } - else if (!auth_reply_callback && clientHasModuleAuthInProgress(c)) { + } else if (!auth_reply_callback && clientHasModuleAuthInProgress(c)) { c->bstate.module_blocked_handle = NULL; addReplyError(c, "Clients undergoing module based authentication can only be blocked on auth"); } else { if (keys) { - blockForKeys(c,BLOCKED_MODULE,keys,numkeys,timeout,flags&REDISMODULE_BLOCK_UNBLOCK_DELETED); + blockForKeys(c,BLOCKED_MODULE,keys,numkeys,c->bstate.timeout,flags&REDISMODULE_BLOCK_UNBLOCK_DELETED); } else { blockClient(c,BLOCKED_MODULE); }