libsubcmd: Avoid SEGV/use-after-free when commands aren't excluded

The array shortening may perform unnecessary array copies.

Before commit 657a3efee4 ("lib subcmd: Avoid memory leak in
exclude_cmds") this was benign, but afterwards this could lead to a
SEGV.

Fixes: 657a3efee4 ("lib subcmd: Avoid memory leak in exclude_cmds")
Signed-off-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Chenyuan Mi <cymi20@fudan.edu.cn>
Cc: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20230707230926.841086-1-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Ian Rogers 2023-07-07 16:09:26 -07:00 committed by Arnaldo Carvalho de Melo
parent ad07149f34
commit 4b96679170
1 changed files with 12 additions and 6 deletions

View File

@ -68,8 +68,13 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
while (ci < cmds->cnt && ei < excludes->cnt) {
cmp = strcmp(cmds->names[ci]->name, excludes->names[ei]->name);
if (cmp < 0) {
zfree(&cmds->names[cj]);
cmds->names[cj++] = cmds->names[ci++];
if (ci == cj) {
ci++;
cj++;
} else {
zfree(&cmds->names[cj]);
cmds->names[cj++] = cmds->names[ci++];
}
} else if (cmp == 0) {
ci++;
ei++;
@ -77,10 +82,11 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
ei++;
}
}
while (ci < cmds->cnt) {
zfree(&cmds->names[cj]);
cmds->names[cj++] = cmds->names[ci++];
if (ci != cj) {
while (ci < cmds->cnt) {
zfree(&cmds->names[cj]);
cmds->names[cj++] = cmds->names[ci++];
}
}
for (ci = cj; ci < cmds->cnt; ci++)
zfree(&cmds->names[ci]);