Skip to content

Modules: handle NULL pointer in BlockClient#4366

Open
soloestoy wants to merge 2 commits into
redis:unstablefrom
soloestoy:module-handle-null-timeout_callback
Open

Modules: handle NULL pointer in BlockClient#4366
soloestoy wants to merge 2 commits into
redis:unstablefrom
soloestoy:module-handle-null-timeout_callback

Conversation

@soloestoy

@soloestoy soloestoy commented Oct 9, 2017

Copy link
Copy Markdown
Contributor

Redis may crash if we pass a NULL timeout_callback to module API RedisModule_BlockClient, because we doesn't check the timeout_callback when the client really reach the timeout.

The timeout_callback can only be executed when it is not NULL, and we should reply -1 to client
when timeout_callback is NULL to tell client that timeout occurs.

@dvirsky

dvirsky commented Oct 9, 2017

Copy link
Copy Markdown
Contributor

@soloestoy it is assumed that the developer will not set a NULL timeout function with a real timeout value. I don't think we should protect from it, especially not in that way.

@soloestoy

soloestoy commented Oct 9, 2017

Copy link
Copy Markdown
Contributor Author

Yes, but I think it is necessary because we allow developers to set NULL timeout function, and we already check the reply_callback function in

void moduleHandleBlockedClients(void) {
    ...
       if (c && bc->reply_callback) {
    ...
}

Why don't we check timeout_callback?

@soloestoy

soloestoy commented Oct 9, 2017

Copy link
Copy Markdown
Contributor Author

Is it better to only allow timeout function be NULL when timeout is zero in the API RedisModule_BlockClient? @dvirsky

@soloestoy

soloestoy commented Oct 11, 2017

Copy link
Copy Markdown
Contributor Author

@dvirsky another question, it seems that we allow developers call RedisModule_Call with "!" flag to replicate commands in reply_callback, see function moduleHandleBlockedClients:

void moduleHandleBlockedClients(void) {
    ...
        if (c && bc->reply_callback) {
            RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
            ctx.flags |= REDISMODULE_CTX_BLOCKED_REPLY;
            ctx.blocked_privdata = bc->privdata;
            ctx.module = bc->module;
            ctx.client = bc->client;
            bc->reply_callback(&ctx,(void**)c->argv,c->argc);
            moduleHandlePropagationAfterCommandCallback(&ctx);
            moduleFreeContext(&ctx);
        }
    ...

Do we allow developers do replication in timeout_callback too? I didn't find the forbidden rule, so I think it's necessary to call moduleHandlePropagationAfterCommandCallback after timeout_callback too.

void moduleBlockedClientTimedOut(client *c) {
    RedisModuleBlockedClient *bc = c->bpop.module_blocked_handle;
    RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
    ctx.flags |= REDISMODULE_CTX_BLOCKED_TIMEOUT;
    ctx.module = bc->module;
    ctx.client = bc->client;
    if (bc->timeout_callback) {
        bc->timeout_callback(&ctx,(void**)c->argv,c->argc);
        moduleHandlePropagationAfterCommandCallback(&ctx);
    } else {
        addReply(c,shared.nullmultibulk);
    }
    moduleFreeContext(&ctx);
}

@antirez

antirez commented Nov 24, 2017

Copy link
Copy Markdown
Contributor

Hello @soloestoy, @dvirsky,

to set a NULL callback with non-zero timeout is indeed an API misuse, however what we could do to fix this instead is to just register a default timeout callback if NULL is passed. One just replying "-ERR blocked module command timed out, but timeout callback is NULL". This will be much more evident and does not need any extra check.

About the second fix, it's odd that people could do actual work in the timeout callback, but there is also no easy way to prevent it, so I think that you fix makes sense here: at least it does not break replication in that case, so I'm merging 5021e3c.

About the other fix, if you agree with the fix, you can write the default timeout handler inside module.c and set it in case it's NULL (even if the timeout it's 0, you never know if the internals could call the function in the future). Thanks for your help!

@antirez

antirez commented Nov 24, 2017

Copy link
Copy Markdown
Contributor

No sorry can't merge just one, the two touch the same code. I'll wait for some update of the PR. Thanks.

@soloestoy

Copy link
Copy Markdown
Contributor Author

OK, I will update this PR later.

@soloestoy soloestoy force-pushed the module-handle-null-timeout_callback branch from 5021e3c to 4574af2 Compare November 27, 2017 09:52
@soloestoy

Copy link
Copy Markdown
Contributor Author

PR updated, please check @antirez

@soloestoy soloestoy force-pushed the module-handle-null-timeout_callback branch from 6640017 to b66fbf9 Compare July 7, 2021 02:30
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants