Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

The array shortening may perform unnecessary array copies.

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

Fixes: 657a3efee43a29d1 ("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>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
4b966791 ad07149f

+12 -6
+12 -6
tools/lib/subcmd/help.c
··· 68 68 while (ci < cmds->cnt && ei < excludes->cnt) { 69 69 cmp = strcmp(cmds->names[ci]->name, excludes->names[ei]->name); 70 70 if (cmp < 0) { 71 - zfree(&cmds->names[cj]); 72 - cmds->names[cj++] = cmds->names[ci++]; 71 + if (ci == cj) { 72 + ci++; 73 + cj++; 74 + } else { 75 + zfree(&cmds->names[cj]); 76 + cmds->names[cj++] = cmds->names[ci++]; 77 + } 73 78 } else if (cmp == 0) { 74 79 ci++; 75 80 ei++; ··· 82 77 ei++; 83 78 } 84 79 } 85 - 86 - while (ci < cmds->cnt) { 87 - zfree(&cmds->names[cj]); 88 - cmds->names[cj++] = cmds->names[ci++]; 80 + if (ci != cj) { 81 + while (ci < cmds->cnt) { 82 + zfree(&cmds->names[cj]); 83 + cmds->names[cj++] = cmds->names[ci++]; 84 + } 89 85 } 90 86 for (ci = cj; ci < cmds->cnt; ci++) 91 87 zfree(&cmds->names[ci]);