From f72d02e934af14f24aab86d4c7d9e96c02ee9cdf Mon Sep 17 00:00:00 2001 From: Mavis Date: Tue, 28 Jul 2026 00:08:02 +0000 Subject: [PATCH] dvi-document: Use g_spawn_sync with argv instead of cmdline string 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, , -o, exporter_filename, context->filename, NULL } The "-s " 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. --- backend/dvi/dvi-document.c | 48 ++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/backend/dvi/dvi-document.c b/backend/dvi/dvi-document.c index bdbc15f1..873207d6 100644 --- a/backend/dvi/dvi-document.c +++ b/backend/dvi/dvi-document.c @@ -368,27 +368,41 @@ dvi_document_file_exporter_do_page (EvFileExporter *exporter, static void dvi_document_file_exporter_end (EvFileExporter *exporter) { - gchar *command_line; gint exit_stat; GError *err = NULL; gboolean success; - + gchar *pages; + gsize pages_len; + DviDocument *dvi_document = DVI_DOCUMENT(exporter); - gchar* quoted_filename = g_shell_quote (dvi_document->context->filename); - - command_line = g_strdup_printf ("dvipdfm %s -o %s %s", /* dvipdfm -s 1,2,.., -o exporter_filename dvi_filename */ - dvi_document->exporter_opts->str, - dvi_document->exporter_filename, - quoted_filename); - g_free (quoted_filename); - - success = g_spawn_command_line_sync (command_line, - NULL, - NULL, - &exit_stat, - &err); - - g_free (command_line); + + /* exporter_opts is built as "-s 1,2,3,...". For an argv[] spawn we + * need to split it into two separate arguments and strip the trailing + * comma that do_page() appends after every page index. Using + * g_spawn_sync() with an explicit argv[] array (rather than building a + * command-line string and going through g_spawn_command_line_sync()) + * removes the shell-tokenizer from the trust boundary: each element is + * passed verbatim to dvipdfm. + */ + pages = g_strdup (dvi_document->exporter_opts->str + strlen ("-s ")); + pages_len = strlen (pages); + if (pages_len > 0 && pages[pages_len - 1] == ',') + pages[pages_len - 1] = '\0'; + + gchar *argv[] = { + (gchar *) "dvipdfm", + (gchar *) "-s", + pages, + (gchar *) "-o", + dvi_document->exporter_filename, + dvi_document->context->filename, + NULL + }; + + success = g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL, + NULL, &exit_stat, &err); + + g_free (pages); if (success == FALSE) { g_warning ("Error: %s", err->message);