Skip to content

lib/utilunix: free the words a command is cut into - #5152

Merged
mc-worker merged 2 commits into
MidnightCommander:masterfrom
ilia-maslakov:fix-utilunix-arg-array-leak
Sep 12, 2026
Merged

lib/utilunix: free the words a command is cut into#5152
mc-worker merged 2 commits into
MidnightCommander:masterfrom
ilia-maslakov:fix-utilunix-arg-array-leak

Conversation

@ilia-maslakov

Copy link
Copy Markdown
Contributor

Problem

my_system_make_arg_array() returns an array whose contents belong to two
different owners. For EXECUTE_AS_SHELL, and for an empty command, it holds
string literals and a NULL; otherwise it holds the words str_tokenize()
allocated. my_systemv_flags() then frees the array with g_ptr_array_free (args_array, TRUE), which frees the array and nothing in it, so every command
that is not run through a shell leaves its words behind.

It is a small leak (one allocation per word of the command line), but it happens
on every my_system() / my_systeml() / my_systemv_flags() call that runs a
program directly — the user menu, the external editor and viewer, extfs helpers.

18 bytes in 1 blocks are definitely lost in loss record 16 of 44
   at 0x4846828: malloc
   by 0x4D6BAC9: g_malloc
   by 0x4D81597: g_strndup
   by 0x12D9E3: str_tokenize (tokenize.c:245)
   by 0x121347: my_system_make_arg_array (utilunix.c:213)
   by 0x121347: my_systemv_flags (utilunix.c:525)
   by 0x1213FF: my_systeml (utilunix.c:453)

Change

The array owns everything it holds: it is created with g_free as its element
free function, the literals are copied into it, and my_systemv_flags() copies
the caller's argv entries as it appends them. That is a handful of g_strdup()
next to a fork() and an execvp().

A command of nothing but blanks is handled on the way: str_tokenize() returns
NULL for it, and g_ptr_array_index (args_array, 0) in my_systemv_flags()
then dereferences it. Such a command is the same as no command at all, and now
takes the same path as an empty one.

Two test-side fixes come with it, both found by the same valgrind run and both
unrelated to the leak:

  • the mocked sigaction() never wrote into the oldact it was handed, so
    VERIFY_SIGACTION__IS_RESTORED() compared bytes that nobody had ever written;
  • mc_pstream_get_long_file_list_test never freed the pipe it opened.

Verified

Ubuntu 24.04, --enable-werror: builds with no compiler warnings, make check
69/69. The four lib/utilunix tests under
valgrind --leak-check=full --errors-for-leak-kinds=definite --track-origins=yes
report nothing; before the change all four failed.

my_system_make_arg_array() returns an array whose contents belong to two
different owners: string literals for EXECUTE_AS_SHELL and for an empty command,
the words str_tokenize() allocated otherwise.  my_systemv_flags() frees it with
g_ptr_array_free (args_array, TRUE), which frees the array and nothing in it, so
every command that is not run through a shell leaves its words behind.

Let the array own everything it holds and copy what it is given.

A command of nothing but blanks tokenizes to nothing at all: str_tokenize()
returns NULL, which g_ptr_array_index (args_array, 0) then dereferences.  Such a
command is no command at all, and now takes the same path as an empty one.

Signed-off-by: Ilia Maslakov <il.smind@gmail.com>
The mocked sigaction() never wrote into the oldact it was handed, so
VERIFY_SIGACTION__IS_RESTORED() compared bytes that nobody had ever written, and
mc_pstream_get_long_file_list_test never freed the pipe it opened.

Signed-off-by: Ilia Maslakov <il.smind@gmail.com>
@github-actions github-actions Bot added needs triage Needs triage by maintainers prio: medium Has the potential to affect progress labels Sep 11, 2026
@github-actions github-actions Bot added this to the Future Releases milestone Sep 11, 2026
@mc-worker
mc-worker merged commit cd6ad96 into MidnightCommander:master Sep 12, 2026
4 checks passed
@mc-worker

Copy link
Copy Markdown
Contributor

Thanks!

@mc-worker
mc-worker requested review from aborodin and mc-worker and removed request for aborodin September 12, 2026 09:59
@mc-worker mc-worker added area: core Issues not related to a specific subsystem and removed needs triage Needs triage by maintainers labels Sep 12, 2026
@mc-worker mc-worker modified the milestones: Future Releases, 4.9.0 Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: core Issues not related to a specific subsystem prio: medium Has the potential to affect progress

Development

Successfully merging this pull request may close these issues.

2 participants