git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v4] pager: fix crash when pager program doesn't exist

From
Enzo Matsumiya <ematsumiya@suse.de>
Date
Nov 25, 2021, 00:02 UTC
Message-ID
<20211125000239.2336-1-ematsumiya@suse.de>

When prepare_cmd() fails for, e.g., pager process setup, child_process_clear() frees the memory in pager_process.args, but .argv was pointed to pager_process.args.v earlier in start_command(), so it's now a dangling pointer.

setup_pager() is then called a second time, from cmd_log_init_finish() in this case, and any further operations using its .argv, e.g. strvec_*, will use the dangling pointer and eventually crash. According to trivial tests, setup_pager() is not called twice if the first call is successful.

This patch makes sure that pager_process is properly initialized on setup_pager(). Drop CHILD_PROCESS_INIT from its declaration since it's no longer really necessary.

Add a test to catch possible regressions.

Reproducer: $ git config pager.show INVALID_PAGER $ git show $VALID_COMMIT error: cannot run INVALID_PAGER: No such file or directory [1] 3619 segmentation fault (core dumped) git show $VALID_COMMIT

Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
---
Changes to v3:
 - change test description, as per Eric's suggestion
 - drop CHILD_PROCESS_INIT, as per Jeff's suggestion
Changes to v2:
 - move child_process_init() to setup_pager(), as other callers of
   child_process_clear() might've not expected .argv to change
 - add a test case with the reproducer of the original bug
Changes to v1:
 * Implement all of Jeff's suggestions:
   - remove double frees to .argv
   - discard the idea of falling back to DEFAULT_PAGER
   - replace memset() in child_process_clear() by child_process_init()
   - update/improve commit message
 pager.c          | 4 +++-
 t/t7006-pager.sh | 5 +++++
 2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/pager.c b/pager.c
index 52f27a6765c8..27877f8ebbc1 100644
--- a/pager.c
+++ b/pager.c
@@ -8,7 +8,7 @@
 #define DEFAULT_PAGER "less"
 #endif
 
-static struct child_process pager_process = CHILD_PROCESS_INIT;
+static struct child_process pager_process;
 static const char *pager_program;
 
 /* Is the value coming back from term_columns() just a guess? */
@@ -124,6 +124,8 @@ void setup_pager(void)
 
 	setenv("GIT_PAGER_IN_USE", "true", 1);
 
+	child_process_init(&pager_process);
+
 	/* spawn the pager */
 	prepare_pager_args(&pager_process, pager);
 	pager_process.in = -1;
diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh
index 0e7cf75435ec..eed680a2b1ee 100755
--- a/t/t7006-pager.sh
+++ b/t/t7006-pager.sh
@@ -786,4 +786,9 @@ test_expect_success TTY 'git returns SIGPIPE on propagated signals from pager' '
 	test_path_is_file pager-used
 '
 
+test_expect_success TTY 'non-existent pager doesnt cause crash' '
+	test_config pager.show invalid-pager &&
+	test_terminal git show
+'
+
 test_done
-- 
2.33.1
Next: Junio C Hamano
Message 1 of 2 in “pager: fix crash when pager program doesn't exist”
  1. pager: fix crash when pager program doesn't existEnzo Matsumiya, Nov 25, 2021
  2. Junio C HamanoNov 26, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.