Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do command existence and arity checks when loading AOF to avoid crash #1614

Open
wants to merge 2 commits into
base: unstable
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/aof.c
Original file line number Diff line number Diff line change
Expand Up @@ -1532,10 +1532,11 @@ int loadSingleAppendOnlyFile(char *filename) {
}

/* Command lookup */
cmd = lookupCommand(argv, argc);
if (!cmd) {
serverLog(LL_WARNING, "Unknown command '%s' reading the append only file %s", (char *)argv[0]->ptr,
filename);
sds err = NULL;
fakeClient->cmd = fakeClient->lastcmd = cmd = lookupCommand(argv, argc);
if ((!cmd && !commandCheckExistence(fakeClient, &err)) || (cmd && !commandCheckArity(cmd, argc, &err))) {
serverLog(LL_WARNING, "Error reading the append only file %s, error: %s", filename, err);
sdsfree(err);
freeClientArgv(fakeClient);
ret = AOF_FAILED;
goto cleanup;
Expand All @@ -1544,7 +1545,6 @@ int loadSingleAppendOnlyFile(char *filename) {
if (cmd->proc == multiCommand) valid_before_multi = valid_up_to;

/* Run the command in the context of a fake client */
fakeClient->cmd = fakeClient->lastcmd = cmd;
if (fakeClient->flag.multi && fakeClient->cmd->proc != execCommand) {
/* Note: we don't have to attempt calling evalGetCommandFlags,
* since this is AOF, the checks in processCommand are not made
Expand Down
3 changes: 1 addition & 2 deletions src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -3911,7 +3911,7 @@ void afterCommand(client *c) {
int commandCheckExistence(client *c, sds *err) {
if (c->cmd) return 1;
if (!err) return 0;
if (isContainerCommandBySds(c->argv[0]->ptr)) {
if (isContainerCommandBySds(c->argv[0]->ptr) && c->argc >= 2) {
/* If we can't find the command but argv[0] by itself is a command
* it means we're dealing with an invalid subcommand. Print Help. */
sds cmd = sdsnew((char *)c->argv[0]->ptr);
Expand Down Expand Up @@ -4025,7 +4025,6 @@ int processCommand(client *c) {
return C_OK;
}


/* Check if the command is marked as protected and the relevant configuration allows it */
if (c->cmd->flags & CMD_PROTECTED) {
if ((c->cmd->proc == debugCommand && !allowProtectedAction(server.enable_debug_cmd, c)) ||
Expand Down
43 changes: 42 additions & 1 deletion tests/integration/aof.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ tags {"aof external:skip"} {

start_server_aof_ex [list dir $server_path aof-load-truncated yes] [list wait_ready false] {
test "Unknown command: Server should have logged an error" {
wait_for_log_messages 0 {"*Unknown command 'bla' reading the append only file*"} 0 10 1000
wait_for_log_messages 0 {"*unknown command 'bla'*"} 0 10 1000
}
}

Expand Down Expand Up @@ -693,6 +693,47 @@ tags {"aof cluster external:skip"} {
assert_equal [r ping] {PONG}
}
}

test {Test command check in aof won't crash} {
# cluster, wrong number of arguments for 'cluster' command
create_aof $aof_dirpath $aof_file { append_to_aof [formatCommand cluster] }
create_aof_manifest $aof_dirpath $aof_manifest_file { append_to_manifest "file appendonly.aof.1.incr.aof seq 1 type i\n" }
start_server_aof_ex [list dir $server_path] [list wait_ready false] {
wait_for_condition 100 50 {
! [is_alive [srv pid]]
} else {
fail "AOF loading didn't fail"
}
assert_equal 1 [count_message_lines $server_path/stdout "wrong number of arguments for 'cluster' command"]
}
clean_aof_persistence $aof_dirpath

# cluster slots-xxx, unknown subcommand 'slots-xxx'
create_aof $aof_dirpath $aof_file { append_to_aof [formatCommand cluster slots-xxx] }
create_aof_manifest $aof_dirpath $aof_manifest_file { append_to_manifest "file appendonly.aof.1.incr.aof seq 1 type i\n" }
start_server_aof_ex [list dir $server_path] [list wait_ready false] {
wait_for_condition 100 50 {
! [is_alive [srv pid]]
} else {
fail "AOF loading didn't fail"
}
assert_equal 1 [count_message_lines $server_path/stdout "unknown subcommand 'slots-xxx'"]
}
clean_aof_persistence $aof_dirpath

# cluster slots xxx, wrong number of arguments for 'cluster|slots' command
create_aof $aof_dirpath $aof_file { append_to_aof [formatCommand cluster slots xxx] }
create_aof_manifest $aof_dirpath $aof_manifest_file { append_to_manifest "file appendonly.aof.1.incr.aof seq 1 type i\n" }
start_server_aof_ex [list dir $server_path] [list wait_ready false] {
wait_for_condition 100 50 {
![is_alive [srv pid]]
} else {
fail "AOF loading didn't fail"
}
assert_equal 1 [count_message_lines $server_path/stdout "wrong number of arguments for 'cluster|slots' command"]
}
clean_aof_persistence $aof_dirpath
}
}

set ::singledb $old_singledb
Loading