From 14260177188cd1f9ae86fabeee4ad148f761166f Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 10 Apr 2020 19:52:27 -0400 Subject: [PATCH 1/3] wt-status-deserialize: fix crash when -v is used Fix crash in `git status -v` by setting `des_s->repo` to a non-null value. Upstream changes to eliminate use of `the_repository` added a `repo` field to `struct status`. And calls in `wt-status.c` to `repo_init_revisions()` were changed to pass `s->repo` rather than `the_repository`. The status deserialization code was not updated to actually set `s->repo` before common code passed the value to OID routines. This caused a segfault when verbose output was requested. Signed-off-by: Jeff Hostetler --- wt-status-deserialize.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wt-status-deserialize.c b/wt-status-deserialize.c index 49190ed7fc5ffe..55110a68036260 100644 --- a/wt-status-deserialize.c +++ b/wt-status-deserialize.c @@ -690,6 +690,7 @@ static int wt_deserialize_fd(const struct wt_status *cmd_s, struct wt_status *de /* * Copy over display-related fields from the current command. */ + des_s->repo = cmd_s->repo; des_s->verbose = cmd_s->verbose; /* amend */ /* whence */ From 5999de11377e2a90630d575ee5289f1fd511dea3 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 10 Apr 2020 21:14:44 -0400 Subject: [PATCH 2/3] status: disable deserialize when verbose output requested. Disable deserialization when verbose output requested. Verbose mode causes Git to print diffs for modified files. This requires the index to be loaded to have the currently staged OID values. Without loading the index, verbose output make it look like everything was deleted. Signed-off-by: Jeff Hostetler --- builtin/commit.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/builtin/commit.c b/builtin/commit.c index d54deb176da7c2..669771199b2823 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -1592,6 +1592,22 @@ int cmd_status(int argc, const char **argv, const char *prefix) */ try_deserialize = (!do_serialize && (do_implicit_deserialize || do_explicit_deserialize)); + + /* + * Disable deserialize when verbose is set because it causes us to + * print diffs for each modified file, but that requires us to have + * the index loaded and we don't want to do that (at least not now for + * this seldom used feature). My fear is that would further tangle + * the merge conflict with upstream. + * + * TODO Reconsider this in the future. + */ + if (try_deserialize && verbose) { + trace2_data_string("status", the_repository, "deserialize/reject", + "args/verbose"); + try_deserialize = 0; + } + if (try_deserialize) goto skip_init; /* From 509f9cd2815d189cd22fbaeb26baca4bdbed665c Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 10 Apr 2020 21:18:41 -0400 Subject: [PATCH 3/3] t7524: add test for verbose status deserialzation Verify that `git status --deserialize=x -v` does not crash and generates the same output as a normal (scanning) status command. These issues are described in the previous 2 commits. Signed-off-by: Jeff Hostetler --- t/t7524-serialized-status.sh | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/t/t7524-serialized-status.sh b/t/t7524-serialized-status.sh index 53e074de8f928e..97d50c84cd0db8 100755 --- a/t/t7524-serialized-status.sh +++ b/t/t7524-serialized-status.sh @@ -387,4 +387,43 @@ EOF ' +test_expect_success 'ensure deserialize -v does not crash' ' + + git init verbose_test && + touch verbose_test/a && + touch verbose_test/b && + touch verbose_test/c && + git -C verbose_test add a b c && + git -C verbose_test commit -m abc && + + echo green >>verbose_test/a && + git -C verbose_test add a && + echo red_1 >>verbose_test/b && + echo red_2 >verbose_test/dirt && + + git -C verbose_test status >output.ref && + git -C verbose_test status -v >output.ref_v && + + git -C verbose_test --no-optional-locks status --serialize=../verbose_test.dat >output.ser.long && + git -C verbose_test --no-optional-locks status --serialize=../verbose_test.dat_v -v >output.ser.long_v && + + # Verify that serialization does not affect the status output itself. + test_i18ncmp output.ref output.ser.long && + test_i18ncmp output.ref_v output.ser.long_v && + + GIT_TRACE2_PERF="$(pwd)"/verbose_test.log \ + git -C verbose_test status --deserialize=../verbose_test.dat >output.des.long && + + # Verify that normal deserialize was actually used and produces the same result. + test_i18ncmp output.ser.long output.des.long && + grep -q "deserialize/result:ok" verbose_test.log && + + GIT_TRACE2_PERF="$(pwd)"/verbose_test.log_v \ + git -C verbose_test status --deserialize=../verbose_test.dat_v -v >output.des.long_v && + + # Verify that vebose mode produces the same result because verbose was rejected. + test_i18ncmp output.ser.long_v output.des.long_v && + grep -q "deserialize/reject:args/verbose" verbose_test.log_v +' + test_done