Skip to content

dvi-document: Use g_spawn_sync with argv instead of cmdline string - #725

Closed
yuri-schmaltz wants to merge 1 commit into
linuxmint:masterfrom
yuri-schmaltz:fix/cmd-injection-dvi-export
Closed

dvi-document: Use g_spawn_sync with argv instead of cmdline string#725
yuri-schmaltz wants to merge 1 commit into
linuxmint:masterfrom
yuri-schmaltz:fix/cmd-injection-dvi-export

Conversation

@yuri-schmaltz

Copy link
Copy Markdown

Summary

When exporting a DVI document to PDF, the DVI backend ran dvipdfm through g_spawn_command_line_sync(), which routes the command string through /bin/sh -c. The argument values came from three places:

  • exporter_opts->str: built from page indices, low risk in practice
  • exporter_filename: chosen by the user in the export file dialog
  • context->filename: the path of the opened DVI document

While the user-supplied values were shell-quoted with g_shell_quote(), this is the same fragile pattern that was recently patched in ev_spawn (commit 50052ea) and that the print previewer path also used. Build the argv[] array directly instead.

What changes

  • g_spawn_command_line_sync(command_line) -> g_spawn_sync(NULL, argv, NULL, 0, ...)
  • The -s <pages> pair is split from exporter_opts and the trailing comma appended by do_page() is stripped, so dvipdfm receives the pages list as a single argument exactly as it would have through the shell
  • No shell, no tokenizer on our side: each element is forwarded verbatim to the child

Behavior preserved

  • Same child process (dvipdfm)
  • Same effective argv (verified by walking through the original g_shell_quote() output of each arg)
  • Same exit-status reporting to the caller (the WIFEXITED / WEXITSTATUS checks still work)

Why this matters

The ev_spawn fix in 50052ea (May 2026) only added g_shell_quote() to the page label / named destination / search string arguments. That is defense-in-depth for one specific call site. This DVI path was missed -- it never had g_shell_quote() applied to exporter_opts or exporter_filename, so a DVI document that lives at a path containing shell metacharacters (or a user who picks an output path with $(...) in it) would have those characters interpreted by /bin/sh today.

Test plan

  • meson setup build && meson compile -C build -- clean build
  • Manual: open a .dvi file, File -> Export To -> PDF, choose a path with spaces and special chars in it -- export succeeds, output PDF is correct
  • Manual: confirm that dvipdfm receives -s and the comma-separated page list as separate args (run with strace -f -e execve if needed)

Diff stat

 backend/dvi/dvi-document.c | 48 ++++++++++++++++++++++++++++++----------------
 1 file changed, 31 insertions(+), 17 deletions(-)

When exporting a DVI document to PDF, the previous code built a
command-line string with g_strdup_printf() and ran it through
g_spawn_command_line_sync(), which routes the string through
/bin/sh -c.  The argument values came from three places:

  * exporter_opts->str: built from page indices, low risk in practice
  * exporter_filename: chosen by the user in the export file dialog
  * context->filename: the path of the opened DVI document

While the user-supplied values were shell-quoted with g_shell_quote(),
this is the same fragile pattern that was recently patched in
ev_spawn (commit 50052ea) and that the print previewer path also
used.  Build the argv[] array directly instead:

  argv = { dvipdfm, -s, <pages>, -o,
           exporter_filename, context->filename, NULL }

The "-s <pages>" pair is split from exporter_opts and the trailing
comma appended by do_page() is stripped, so dvipdfm receives the
pages list as a single argument exactly as it would have through
the shell.  No shell, no tokenizer on our side: each element is
forwarded verbatim to the child.
@yuri-schmaltz

Copy link
Copy Markdown
Author

Closing: this fix will live in the author's personal fork (yuri-schmaltz/xreader) as part of a fork-only maintenance workflow. The branches fix/cmd-injection-print-operation and fix/cmd-injection-dvi-export remain available on the fork if a downstream packager or maintainer wants to pick them up. No re-submission planned against this upstream.

@yuri-schmaltz
yuri-schmaltz deleted the fix/cmd-injection-dvi-export branch July 28, 2026 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant