diff --git a/src/multi.c b/src/multi.c index b02457bb9..4171131b7 100644 --- a/src/multi.c +++ b/src/multi.c @@ -159,7 +159,7 @@ void execCommandAbort(client *c, sds error) { void execCommand(client *c) { int j; robj **orig_argv; - int orig_argc; + int orig_argc, orig_argv_len; struct redisCommand *orig_cmd; int was_master = server.masterhost == NULL; @@ -201,11 +201,12 @@ void execCommand(client *c) { server.in_exec = 1; orig_argv = c->argv; + orig_argv_len = c->argv_len; orig_argc = c->argc; orig_cmd = c->cmd; addReplyArrayLen(c,c->mstate.count); for (j = 0; j < c->mstate.count; j++) { - c->argc = c->mstate.commands[j].argc; + c->argv_len = c->argc = c->mstate.commands[j].argc; c->argv = c->mstate.commands[j].argv; c->cmd = c->mstate.commands[j].cmd; @@ -252,6 +253,7 @@ void execCommand(client *c) { c->flags &= ~CLIENT_DENY_BLOCKING; c->argv = orig_argv; + c->argv_len = orig_argv_len; c->argc = orig_argc; c->cmd = orig_cmd; discardTransaction(c); diff --git a/tests/unit/protocol.tcl b/tests/unit/protocol.tcl index 4f185d9bd..ec08e2d36 100644 --- a/tests/unit/protocol.tcl +++ b/tests/unit/protocol.tcl @@ -203,6 +203,23 @@ start_server {tags {"protocol network"}} { r mset {*}$args assert_equal [r get "{k}2"] v2 } + + test "test argument rewriting - issue 9598" { + # INCRBYFLOAT uses argument rewriting for correct float value propagation. + # We use it to make sure argument rewriting works properly. It's important + # this test is run under valgrind to verify there are no memory leaks in + # arg buffer handling. + r flushdb + + # Test normal argument handling + r set k 0 + assert_equal [r incrbyfloat k 1.0] 1 + + # Test argument handing in multi-state buffers + r multi + r incrbyfloat k 1.0 + assert_equal [r exec] 2 + } }