Re: format-patch crashes with a huge patchset

2014-05-20 Thread Jeff King
On Mon, May 19, 2014 at 10:35:56PM +0300, Michael S. Tsirkin wrote:

 I tried to fump the whole history of qemu with format-patch.
 It crashes both with v2.0.0-rc2-21-g6087111
 and with git 1.8.3.1:
 
 ~/opt/libexec/git-core/git-format-patch --follow -o patches/all
 e63c3dc74bfb90e4522d075d0d5a7600c5145745..

You can't use --follow without specifying a single pathspec. Running
git log --follow notices and blocks this, but format-patch doesn't
(and segfaults later when the follow code assumes there is a pathspec).

I think we need:

-- 8 --
Subject: move --follow needs one pathspec rule to diff_setup_done

Because of the way --follow is implemented, we must have
exactly one pathspec. git log enforces this restriction,
but other users of the revision traversal code do not. For
example, git format-patch --follow will segfault during
try_to_follow_renames, as we have no pathspecs at all.

We can push this check down into diff_setup_done, which is
probably a better place anyway. It is the diff code that
introduces this restriction, so other parts of the code
should not need to care themselves.

Reported-by: Michael S. Tsirkin m...@redhat.com
Signed-off-by: Jeff King p...@peff.net
---
I didn't include a test, as I don't think the current behavior is what
we want in the long run. That is, it would be nice if eventually
--follow learned to be more flexible. Any test for this would
necessarily be looking for the opposite of that behavior. But maybe it's
worth it to just have in the meantime, and anyone who works on --follow
can rip out the test.

 builtin/log.c | 8 ++--
 diff.c| 3 +++
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/builtin/log.c b/builtin/log.c
index 39e8836..3b6a6bb 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -158,13 +158,9 @@ static void cmd_log_init_finish(int argc, const char 
**argv, const char *prefix,
if (rev-show_notes)
init_display_notes(rev-notes_opt);
 
-   if (rev-diffopt.pickaxe || rev-diffopt.filter)
+   if (rev-diffopt.pickaxe || rev-diffopt.filter ||
+   DIFF_OPT_TST(rev-diffopt, FOLLOW_RENAMES))
rev-always_show_header = 0;
-   if (DIFF_OPT_TST(rev-diffopt, FOLLOW_RENAMES)) {
-   rev-always_show_header = 0;
-   if (rev-diffopt.pathspec.nr != 1)
-   usage(git logs can only follow renames on one pathname 
at a time);
-   }
 
if (source)
rev-show_source = 1;
diff --git a/diff.c b/diff.c
index f72769a..68bb8c5 100644
--- a/diff.c
+++ b/diff.c
@@ -3325,6 +3325,9 @@ void diff_setup_done(struct diff_options *options)
}
 
options-diff_path_counter = 0;
+
+   if (DIFF_OPT_TST(options, FOLLOW_RENAMES)  options-pathspec.nr != 1)
+   die(_(--follow requires exactly one pathspec));
 }
 
 static int opt_arg(const char *arg, int arg_short, const char *arg_long, int 
*val)
-- 
2.0.0.rc1.436.g03cb729

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: format-patch crashes with a huge patchset

2014-05-20 Thread Junio C Hamano
Jeff King p...@peff.net writes:

 On Mon, May 19, 2014 at 10:35:56PM +0300, Michael S. Tsirkin wrote:

 I tried to fump the whole history of qemu with format-patch.
 It crashes both with v2.0.0-rc2-21-g6087111
 and with git 1.8.3.1:
 
 ~/opt/libexec/git-core/git-format-patch --follow -o patches/all
 e63c3dc74bfb90e4522d075d0d5a7600c5145745..

 You can't use --follow without specifying a single pathspec. Running
 git log --follow notices and blocks this, but format-patch doesn't
 (and segfaults later when the follow code assumes there is a pathspec).

 I think we need:

Looks sensible.  Intrestingly enough, this dates all the way back to
the original 750f7b66 (Finally implement git log --follow,
2007-06-19).

Re-reading the log message of that commit was amusing for other
reasons, by the way (the most interesting part comes after One
thing to look out for: and especially Put another way:).

 -- 8 --
 Subject: move --follow needs one pathspec rule to diff_setup_done

 Because of the way --follow is implemented, we must have
 exactly one pathspec. git log enforces this restriction,
 but other users of the revision traversal code do not. For
 example, git format-patch --follow will segfault during
 try_to_follow_renames, as we have no pathspecs at all.

 We can push this check down into diff_setup_done, which is
 probably a better place anyway. It is the diff code that
 introduces this restriction, so other parts of the code
 should not need to care themselves.

 Reported-by: Michael S. Tsirkin m...@redhat.com
 Signed-off-by: Jeff King p...@peff.net
 ---
 I didn't include a test, as I don't think the current behavior is what
 we want in the long run. That is, it would be nice if eventually
 --follow learned to be more flexible. Any test for this would
 necessarily be looking for the opposite of that behavior. But maybe it's
 worth it to just have in the meantime, and anyone who works on --follow
 can rip out the test.

  builtin/log.c | 8 ++--
  diff.c| 3 +++
  2 files changed, 5 insertions(+), 6 deletions(-)

 diff --git a/builtin/log.c b/builtin/log.c
 index 39e8836..3b6a6bb 100644
 --- a/builtin/log.c
 +++ b/builtin/log.c
 @@ -158,13 +158,9 @@ static void cmd_log_init_finish(int argc, const char 
 **argv, const char *prefix,
   if (rev-show_notes)
   init_display_notes(rev-notes_opt);
  
 - if (rev-diffopt.pickaxe || rev-diffopt.filter)
 + if (rev-diffopt.pickaxe || rev-diffopt.filter ||
 + DIFF_OPT_TST(rev-diffopt, FOLLOW_RENAMES))
   rev-always_show_header = 0;
 - if (DIFF_OPT_TST(rev-diffopt, FOLLOW_RENAMES)) {
 - rev-always_show_header = 0;
 - if (rev-diffopt.pathspec.nr != 1)
 - usage(git logs can only follow renames on one pathname 
 at a time);
 - }
  
   if (source)
   rev-show_source = 1;
 diff --git a/diff.c b/diff.c
 index f72769a..68bb8c5 100644
 --- a/diff.c
 +++ b/diff.c
 @@ -3325,6 +3325,9 @@ void diff_setup_done(struct diff_options *options)
   }
  
   options-diff_path_counter = 0;
 +
 + if (DIFF_OPT_TST(options, FOLLOW_RENAMES)  options-pathspec.nr != 1)
 + die(_(--follow requires exactly one pathspec));
  }
  
  static int opt_arg(const char *arg, int arg_short, const char *arg_long, int 
 *val)
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


format-patch crashes with a huge patchset

2014-05-19 Thread Michael S. Tsirkin
I tried to fump the whole history of qemu with format-patch.
It crashes both with v2.0.0-rc2-21-g6087111
and with git 1.8.3.1:

~/opt/libexec/git-core/git-format-patch --follow -o patches/all
e63c3dc74bfb90e4522d075d0d5a7600c5145745..

Backtrace:


Program received signal SIGSEGV, Segmentation fault.
0x0814d9d5 in try_to_follow_renames (opt=0xc8e4,
base=base@entry=0x816e4fe , t2=0xbdf0, t1=0xbddc) at
tree-diff.c:227
227 diff_opts.single_follow = opt-pathspec.items[0].match;
Missing separate debuginfos, use: debuginfo-install
openssl-libs-1.0.1e-37.fc19.1.i686
(gdb) p opt
$1 = (struct diff_options *) 0xc8e4
(gdb) where
#0  0x0814d9d5 in try_to_follow_renames (opt=0xc8e4,
base=base@entry=0x816e4fe , t2=0xbdf0, t1=0xbddc) at
tree-diff.c:227
#1  diff_tree_sha1 (old=0x97469b4
\372\022\366\336k\345\236\362\062K\021\236\300\227\036\302\217\251\202f, 
new=new@entry=0x9746994 $\305H\250)\237\203\266ya\311W\n\274
\n\027^*\221, base=base@entry=0x816e4fe , opt=opt@entry=0xc8e4)
at tree-diff.c:305
#2  0x080fb83d in log_tree_diff (log=0xbf28, commit=0x9734730,
opt=0xc618) at log-tree.c:780
#3  log_tree_commit (opt=opt@entry=0xc618,
commit=commit@entry=0x9734730) at log-tree.c:810
#4  0x08088406 in cmd_format_patch (argc=optimized out,
argv=0xccc4, prefix=0x0) at builtin/log.c:1510
#5  0x0804c666 in run_builtin (argv=0xccc4, argc=5, p=0x81cb524
commands+420) at git.c:314
#6  handle_builtin (argc=5, argv=0xccc4) at git.c:487
#7  0x0804bc22 in main (argc=5, av=0xccc4) at git.c:584
(gdb) p opt-pathspec.items
$2 = (struct pathspec_item *) 0x0


Did not debug further: could be related to the fact
swap is disabled on my box, so attempts to allocate
huge amounts of RAM might fail.

Still should not segv I think ...

-- 
MST
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html