{"thread":{"id":"22307","subject":"git-merge segfault in 1.6.6 and master","startedAt":"2010-01-20T16:17:56Z","lastAt":"2010-01-22T00:38:56Z","messageCount":10,"participants":["Tim Olsen","Junio C Hamano","Miklos Vajna"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"132201","messageId":"hj7abm$5vc$1@ger.gmane.org","threadId":"22307","inReplyTo":null,"subject":"git-merge segfault in 1.6.6 and master","fromName":"Tim Olsen","fromEmail":"tim@brooklynpenguin.com","sentAt":"2010-01-20T16:17:56Z","receivedAt":"2010-01-20T16:17:56Z","isPatch":false,"sender":{"key":"tim@brooklynpenguin.com","avatar":"https://gravatar.com/avatar/a468fd97b6433c4d22252ca75017d30a55046f5715e67b83e62b00a0833deb22?d=mp&s=160"},"body":"The following happens on 1.6.6 and master as of\n5b15950ac414a8a2d4f5eb480712abcc9fe176d2.  The problem goes away if I\nuse the resolve merge strategy instead.\n\ntolsen@neurofunk:~/git/site-build-dav-sync-05 [git:build-dav-sync-05]$\ngdb --args git merge origin/deployed\nGNU gdb (GDB) 7.0-debian\nCopyright (C) 2009 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later\n<http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\nThis GDB was configured as \"x86_64-linux-gnu\".\nFor bug reporting instructions, please see:\n<http://www.gnu.org/software/gdb/bugs/>...\nReading symbols from /usr/local/bin/git...done.\n(gdb) r\nStarting program: /usr/local/bin/git merge origin/deployed\n[Thread debugging using libthread_db enabled]\n\nProgram received signal SIGSEGV, Segmentation fault.\n*__GI_memcmp (s1=0x4, s2=0x77b034, len=20) at memcmp.c:339\n339\tmemcmp.c: No such file or directory.\n\tin memcmp.c\n(gdb) bt full\n#0  *__GI_memcmp (s1=0x4, s2=0x77b034, len=20) at memcmp.c:339\n        srcp1 = <value optimized out>\n        srcp2 = <value optimized out>\n        res = <value optimized out>\n#1  0x0000000000495c12 in hashcmp (sha1=0x4 <Address 0x4 out of bounds>,\nsha2=0x77b034 \"\\304\\037Eg\\262\\367\\256\\367\\376\\061홚\\331\\037\\bQ\\231\\332\",\n<incomplete sequence \\370>) at cache.h:620\nNo locals.\n#2  0x0000000000495ca3 in sha_eq (a=0x4 <Address 0x4 out of bounds>,\nb=0x77b034 \"\\304\\037Eg\\262\\367\\256\\367\\376\\061홚\\331\\037\\bQ\\231\\332\",\n<incomplete sequence \\370>) at merge-recursive.c:60\nNo locals.\n#3  0x0000000000499523 in merge_trees (o=0x7fffffffd5b0, head=0x77b058,\nmerge=0x77b030, common=0x0, result=0x7fffffffd548) at merge-recursive.c:1209\n        code = 8076320\n        clean = 13064\n#4  0x0000000000499a46 in merge_recursive (o=0x7fffffffd5b0,\nh1=0x7932d0, h2=0x793240, ca=0x7b3c00, result=0x7fffffffd628) at\nmerge-recursive.c:1343\n        iter = 0x0\n        merged_common_ancestors = 0x121e360\n        mrtree = 0x7b3c20\n        clean = 0\n#5  0x000000000043eee6 in try_merge_strategy (strategy=0x4f2078\n\"recursive\", common=0x787170, head_arg=0x4f2570 \"HEAD\") at\nbuiltin-merge.c:577\n        clean = 0\n        reversed = 0x7b3c20\n        o = {branch1 = 0x4f2570 \"HEAD\", branch2 = 0x7fffffffdf33\n\"origin/deployed\", subtree_merge = 0, buffer_output = 1, verbosity = 2,\ndiff_rename_limit = -1, merge_rename_limit = -1, call_depth = 0, obuf =\n{alloc = 0, len = 0,\n            buf = 0x775ee8 \"\"}, current_file_set = {items = 0x1220510,\nnr = 11526, alloc = 11552, strdup_strings = 1}, current_directory_set =\n{items = 0x1203b80, nr = 2957, alloc = 2976, strdup_strings = 1}}\n        result = 0x303035302d203031\n        lock = 0x7b3d40\n        index_fd = 15\n        args = 0x7fffffffd6a0\n        i = 0\n        ret = 2\n        j = 0x0\n        buf = {alloc = 0, len = 0, buf = 0x775ee8 \"\"}\n        index_fd = 15\n        lock = 0x7b2900\n#6  0x00000000004407d4 in cmd_merge (argc=1, argv=0x7fffffffda90,\nprefix=0x0) at builtin-merge.c:1134\n        ret = 0\n        result_tree =\n\"\\200\\332\\377\\377\\377\\177\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\024\\000\\000\"\n        buf = {alloc = 60, len = 0, buf = 0x7762d0 \"\"}\n        head_arg = 0x4f2570 \"HEAD\"\n        flag = 1\n        head_invalid = 0\n        i = 0\n        best_cnt = -1\n        merge_was_ok = 0\n        automerge_was_ok = 0\n        common = 0x787170\n        best_strategy = 0x0\n        wt_strategy = 0x4f2078 \"recursive\"\n        remotes = 0x776838\n#7  0x000000000040488f in run_builtin (p=0x729b48, argc=2,\nargv=0x7fffffffda90) at git.c:257\n        status = 1647275105\n        help = 0\n        st = {st_dev = 0, st_ino = 0, st_nlink = 7509264, st_mode =\n4158578380, st_uid = 32767, st_gid = 1, __pad0 = 0, st_rdev = 0, st_size\n= 7508768, st_blksize = 140737340287064, st_blocks =\n3403153865682452481, st_atim = {tv_sec = 0,\n            tv_nsec = 140737488345392}, st_mtim = {tv_sec =\n140737351990853, tv_nsec = 140737488345752}, st_ctim = {tv_sec = 134688,\ntv_nsec = 0}, __unused = {5129592, 140737488346931, 0}}\n        prefix = 0x0\n#8  0x0000000000404a1a in handle_internal_command (argc=2,\nargv=0x7fffffffda90) at git.c:401\n        p = 0x729b48\n        cmd = 0x7fffffffdf2d \"merge\"\n        i = 47\n        commands = {{cmd = 0x4e4871 \"add\", fn = 0x405778 <cmd_add>,\noption = 5}, {cmd = 0x4e4875 \"stage\", fn = 0x405778 <cmd_add>, option =\n5}, {cmd = 0x4e487b \"annotate\", fn = 0x405b84 <cmd_annotate>, option =\n1}, {cmd = 0x4e4884 \"apply\",\n            fn = 0x40da8e <cmd_apply>, option = 0}, {cmd = 0x4e488a\n\"archive\", fn = 0x40e7c6 <cmd_archive>, option = 0}, {cmd = 0x4e4892\n\"bisect--helper\", fn = 0x40ea7c <cmd_bisect__helper>, option = 5}, {cmd\n= 0x4e48a1 \"blame\",\n            fn = 0x413481 <cmd_blame>, option = 1}, {cmd = 0x4e48a7\n\"branch\", fn = 0x415393 <cmd_branch>, option = 1}, {cmd = 0x4e48ae\n\"bundle\", fn = 0x415bb4 <cmd_bundle>, option = 0}, {cmd = 0x4e48b5\n\"cat-file\", fn = 0x416484 <cmd_cat_file>,\n            option = 1}, {cmd = 0x4e48be \"checkout\", fn = 0x4197c5\n<cmd_checkout>, option = 5}, {cmd = 0x4e48c7 \"checkout-index\", fn =\n0x417514 <cmd_checkout_index>, option = 5}, {cmd = 0x4e48d6\n\"check-ref-format\",\n            fn = 0x416cf2 <cmd_check_ref_format>, option = 0}, {cmd =\n0x4e48e7 \"check-attr\", fn = 0x416a73 <cmd_check_attr>, option = 1}, {cmd\n= 0x4e48f2 \"cherry\", fn = 0x437b3e <cmd_cherry>, option = 1}, {cmd =\n0x4e48f9 \"cherry-pick\",\n            fn = 0x456fd1 <cmd_cherry_pick>, option = 5}, {cmd =\n0x4e4905 \"clone\", fn = 0x41b4b5 <cmd_clone>, option = 0}, {cmd =\n0x4e490b \"clean\", fn = 0x41a198 <cmd_clean>, option = 5}, {cmd =\n0x4e4911 \"commit\", fn = 0x41f144 <cmd_commit>,\n            option = 5}, {cmd = 0x4e4918 \"commit-tree\", fn = 0x41c4a0\n<cmd_commit_tree>, option = 1}, {cmd = 0x4e4924 \"config\", fn = 0x420398\n<cmd_config>, option = 0}, {cmd = 0x4e492b \"count-objects\", fn =\n0x420e9a <cmd_count_objects>,\n            option = 1}, {cmd = 0x4e4939 \"describe\", fn = 0x421e8a\n<cmd_describe>, option = 1}, {cmd = 0x4e4942 \"diff\", fn = 0x4238dc\n<cmd_diff>, option = 0}, {cmd = 0x4e4947 \"diff-files\", fn = 0x422454\n<cmd_diff_files>, option = 5}, {\n            cmd = 0x4e4952 \"diff-index\", fn = 0x4226b0 <cmd_diff_index>,\noption = 1}, {cmd = 0x4e495d \"diff-tree\", fn = 0x422bb1 <cmd_diff_tree>,\noption = 1}, {cmd = 0x4e4967 \"fast-export\", fn = 0x42553f\n<cmd_fast_export>, option = 1}, {\n            cmd = 0x4e4973 \"fetch\", fn = 0x429fb8 <cmd_fetch>, option =\n1}, {cmd = 0x4e4979 \"fetch-pack\", fn = 0x4275da <cmd_fetch_pack>, option\n= 1}, {cmd = 0x4e4984 \"fmt-merge-msg\", fn = 0x42b17a\n<cmd_fmt_merge_msg>, option = 1}, {\n            cmd = 0x4e4992 \"for-each-ref\", fn = 0x42d287\n<cmd_for_each_ref>, option = 1}, {cmd = 0x4e499f \"format-patch\", fn =\n0x436a1f <cmd_format_patch>, option = 1}, {cmd = 0x4e49ac \"fsck\", fn =\n0x42eae7 <cmd_fsck>, option = 1}, {\n            cmd = 0x4e49b1 \"fsck-objects\", fn = 0x42eae7 <cmd_fsck>,\noption = 1}, {cmd = 0x4e49be \"gc\", fn = 0x42f26b <cmd_gc>, option = 1},\n{cmd = 0x4e49c1 \"get-tar-commit-id\", fn = 0x45ea9f\n<cmd_get_tar_commit_id>, option = 0}, {\n            cmd = 0x4e49d3 \"grep\", fn = 0x431505 <cmd_grep>, option =\n3}, {cmd = 0x4e49d8 \"help\", fn = 0x4332b8 <cmd_help>, option = 0}, {cmd\n= 0x4e49dd \"init\", fn = 0x43420d <cmd_init_db>, option = 0}, {cmd =\n0x4e49e2 \"init-db\",\n            fn = 0x43420d <cmd_init_db>, option = 0}, {cmd = 0x4e49ea\n\"log\", fn = 0x43560b <cmd_log>, option = 3}, {cmd = 0x4e49ee \"ls-files\",\nfn = 0x438f72 <cmd_ls_files>, option = 1}, {cmd = 0x4e49f7 \"ls-tree\", fn\n= 0x439f6b <cmd_ls_tree>,\n            option = 1}, {cmd = 0x4e49ff \"ls-remote\", fn = 0x43993f\n<cmd_ls_remote>, option = 0}, {cmd = 0x4e4a09 \"mailinfo\", fn = 0x43c72d\n<cmd_mailinfo>, option = 0}, {cmd = 0x4e4a12 \"mailsplit\", fn = 0x43d20c\n<cmd_mailsplit>, option = 0}, {\n            cmd = 0x4e4a1c \"merge\", fn = 0x43fc4b <cmd_merge>, option =\n5}, {cmd = 0x4e4a22 \"merge-base\", fn = 0x440d14 <cmd_merge_base>, option\n= 1}, {cmd = 0x4e4a2d \"merge-file\", fn = 0x440f0a <cmd_merge_file>,\noption = 0}, {\n            cmd = 0x4e4a38 \"merge-ours\", fn = 0x441408 <cmd_merge_ours>,\noption = 1}, {cmd = 0x4e4a43 \"merge-recursive\", fn = 0x4414e2\n<cmd_merge_recursive>, option = 5}, {cmd = 0x4e4a53 \"merge-subtree\", fn\n= 0x4414e2 <cmd_merge_recursive>,\n            option = 5}, {cmd = 0x4e4a61 \"mktree\", fn = 0x441d15\n<cmd_mktree>, option = 1}, {cmd = 0x4e4a68 \"mv\", fn = 0x44210b <cmd_mv>,\noption = 5}, {cmd = 0x4e4a6b \"name-rev\", fn = 0x443251 <cmd_name_rev>,\noption = 1}, {\n            cmd = 0x4e4a74 \"pack-objects\", fn = 0x44821f\n<cmd_pack_objects>, option = 1}, {cmd = 0x4e4a81 \"peek-remote\", fn =\n0x43993f <cmd_ls_remote>, option = 0}, {cmd = 0x4e4a8d \"pickaxe\", fn =\n0x413481 <cmd_blame>, option = 1}, {\n            cmd = 0x4e4a95 \"prune\", fn = 0x449431 <cmd_prune>, option =\n1}, {cmd = 0x4e4a9b \"prune-packed\", fn = 0x448e33 <cmd_prune_packed>,\noption = 1}, {cmd = 0x4e4aa8 \"push\", fn = 0x449cdd <cmd_push>, option =\n1}, {cmd = 0x4e4aad \"read-tree\",\n            fn = 0x44a28d <cmd_read_tree>, option = 1}, {cmd = 0x4e4ab7\n\"receive-pack\", fn = 0x44be59 <cmd_receive_pack>, option = 0}, {cmd =\n0x4e4ac4 \"reflog\", fn = 0x44daf6 <cmd_reflog>, option = 1}, {cmd =\n0x4e4acb \"remote\",\n            fn = 0x4519b9 <cmd_remote>, option = 1}, {cmd = 0x4e4ad2\n\"replace\", fn = 0x451fa9 <cmd_replace>, option = 1}, {cmd = 0x4e4ada\n\"repo-config\", fn = 0x420398 <cmd_config>, option = 0}, {cmd = 0x4e4ae6\n\"rerere\",\n            fn = 0x452698 <cmd_rerere>, option = 1}, {cmd = 0x4e4aed\n\"reset\", fn = 0x4530cf <cmd_reset>, option = 1}, {cmd = 0x4e4af3\n\"rev-list\", fn = 0x4540be <cmd_rev_list>, option = 1}, {cmd = 0x4e4afc\n\"rev-parse\",\n            fn = 0x45537f <cmd_rev_parse>, option = 0}, {cmd = 0x4e4b06\n\"revert\", fn = 0x456f84 <cmd_revert>, option = 5}, {cmd = 0x4e4b0d \"rm\",\nfn = 0x457368 <cmd_rm>, option = 1}, {cmd = 0x4e4b10 \"send-pack\", fn =\n0x458c65 <cmd_send_pack>,\n---Type <return> to continue, or q <return> to quit---\n            option = 1}, {cmd = 0x4e4b1a \"shortlog\", fn = 0x459c27\n<cmd_shortlog>, option = 2}, {cmd = 0x4e4b23 \"show-branch\", fn =\n0x45b3b7 <cmd_show_branch>, option = 1}, {cmd = 0x4e4b2f \"show\", fn =\n0x43511f <cmd_show>, option = 3}, {\n            cmd = 0x4e4b34 \"status\", fn = 0x41ec30 <cmd_status>, option\n= 5}, {cmd = 0x4e4b3b \"stripspace\", fn = 0x45cf9d <cmd_stripspace>,\noption = 0}, {cmd = 0x4e4b46 \"symbolic-ref\", fn = 0x45d0f3\n<cmd_symbolic_ref>, option = 1}, {\n            cmd = 0x4e4b53 \"tag\", fn = 0x45df1e <cmd_tag>, option = 1},\n{cmd = 0x4e4b57 \"tar-tree\", fn = 0x45e8b4 <cmd_tar_tree>, option = 0},\n{cmd = 0x4e4b60 \"unpack-objects\", fn = 0x45fe1f <cmd_unpack_objects>,\noption = 1}, {\n            cmd = 0x4e4b6f \"update-index\", fn = 0x461634\n<cmd_update_index>, option = 1}, {cmd = 0x4e4b7c \"update-ref\", fn =\n0x461fac <cmd_update_ref>, option = 1}, {cmd = 0x4e4b87\n\"update-server-info\", fn = 0x4622f8 <cmd_update_server_info>,\n            option = 1}, {cmd = 0x4e4b9a \"upload-archive\", fn = 0x4627e4\n<cmd_upload_archive>, option = 0}, {cmd = 0x4e4ba9 \"verify-tag\", fn =\n0x4634ba <cmd_verify_tag>, option = 1}, {cmd = 0x4e4bb4 \"version\", fn =\n0x491586 <cmd_version>,\n            option = 0}, {cmd = 0x4e4bbc \"whatchanged\", fn = 0x434df8\n<cmd_whatchanged>, option = 3}, {cmd = 0x4e4bc8 \"write-tree\", fn =\n0x463614 <cmd_write_tree>, option = 1}, {cmd = 0x4e4bd3 \"verify-pack\",\nfn = 0x462fb3 <cmd_verify_pack>,\n            option = 0}, {cmd = 0x4e4bdf \"show-ref\", fn = 0x45cb53\n<cmd_show_ref>, option = 1}, {cmd = 0x4e4be8 \"pack-refs\", fn = 0x448ad0\n<cmd_pack_refs>, option = 1}}\n        ext = \"\"\n#9  0x0000000000404b00 in run_argv (argcp=0x7fffffffd984,\nargv=0x7fffffffd978) at git.c:443\n        done_alias = 0\n#10 0x0000000000404c51 in main (argc=2, argv=0x7fffffffda90) at git.c:514\n        cmd = 0x7fffffffdf2d \"merge\"\n        done_help = 0\n        was_alias = 0\n(gdb)\n"},{"id":"132206","messageId":"7vocko3802.fsf@alter.siamese.dyndns.org","threadId":"22307","inReplyTo":"hj7abm$5vc$1@ger.gmane.org","subject":"Re: git-merge segfault in 1.6.6 and master","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-01-20T19:13:01Z","receivedAt":"2010-01-20T19:13:01Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Tim Olsen <tim@brooklynpenguin.com> writes:\n\n> The following happens on 1.6.6 and master as of\n> 5b15950ac414a8a2d4f5eb480712abcc9fe176d2.  The problem goes away if I\n> use the resolve merge strategy instead.\n\nThanks.\n\nSince you can build and run git yourself, can I ask you to run another\nexperiment with this one-liner patch applied?\n\ndiff --git a/builtin-merge.c b/builtin-merge.c\nindex 82e2a04..08a8f24 100644\n--- a/builtin-merge.c\n+++ b/builtin-merge.c\n@@ -550,7 +550,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,\n \t\treturn error(\"Unable to write index.\");\n \trollback_lock_file(lock);\n \n-\tif (!strcmp(strategy, \"recursive\") || !strcmp(strategy, \"subtree\")) {\n+\tif (0) {\n \t\tint clean;\n \t\tstruct commit *result;\n \t\tstruct lock_file *lock = xcalloc(1, sizeof(struct lock_file));\n\nThis disables the codepath that special-cases the calling convention for\nthese merge strategies, and was introduce by 18668f5 (builtin-merge: avoid\nrun_command_v_opt() for recursive and subtree, 2008-08-28 -- authors Cc'ed\nto ask for help in diagnosing).\n\nIf this experiment \"fixes\" the failure for you, then it would be a sign\nthat the caller (not necessarily in the code in this \"if()\" block) may be\ndoing something wrong (or more likely, not doing enough) before calling\ninto merge_recursive().  I am suspecting that it is not parsing some\ncommit objects properly, e.g. using lookup_commit(SHA-1) and using the\nresult without calling parse_object() on it first, or something similar\nthat is silly but trivial to fix.\n\nAfter the experiment, please revert the above one-liner.  I don't want to\nuse a work-around forever; we'd be better off finding where in the code it\ngoes wrong.  Looking at your gdb trace, I notice...\n\n> (gdb) r\n> Starting program: /usr/local/bin/git merge origin/deployed\n> [Thread debugging using libthread_db enabled]\n> ...\n> #3  0x0000000000499523 in merge_trees (o=0x7fffffffd5b0, head=0x77b058,\n> merge=0x77b030, common=0x0, result=0x7fffffffd548) at merge-recursive.c:1209\n>         code = 8076320\n>         clean = 13064\n\n\"common = NULL\" means merged_common_ancestors->tree is NULL in the caller.\nSomebody is passing a bogus commit in \"ca\" (aka common ancestors) list\nwhen calling merge_recursive(), or forgetting to parse them before calling\nit.  In your debugger could you find out where it comes from and what it\nhas before this call into merge_trees() is made?  Specifically, what the\n\"ca\" list at 0x7b3c00 contains, and how \"merged_common_ancestors\" at\n0x121e360 looks like. in this trace we see below:\n\n> #4  0x0000000000499a46 in merge_recursive (o=0x7fffffffd5b0,\n> h1=0x7932d0, h2=0x793240, ca=0x7b3c00, result=0x7fffffffd628) at\n> merge-recursive.c:1343\n"},{"id":"132233","messageId":"4B577C3F.7040608@brooklynpenguin.com","threadId":"22307","inReplyTo":"7vocko3802.fsf@alter.siamese.dyndns.org","subject":"Re: git-merge segfault in 1.6.6 and master","fromName":"Tim Olsen","fromEmail":"tim@brooklynpenguin.com","sentAt":"2010-01-20T21:57:19Z","receivedAt":"2010-01-20T21:57:19Z","isPatch":false,"sender":{"key":"tim@brooklynpenguin.com","avatar":"https://gravatar.com/avatar/a468fd97b6433c4d22252ca75017d30a55046f5715e67b83e62b00a0833deb22?d=mp&s=160"},"body":"Junio C Hamano wrote:\n> Thanks.\n\nThanks for taking the time to look into this!\n\n> \n> Since you can build and run git yourself, can I ask you to run another\n> experiment with this one-liner patch applied?\n\nIt appears that a segfault still happens with your patch applied, but\nthis time it is caught:\n\ntolsen@neurofunk:~/git/site-build-dav-sync-05 [git:build-dav-sync-05]$\ngit merge origin/deployed\nerror: merge-recursive died of signal 11\nMerge with strategy recursive failed.\ntolsen@neurofunk:~/git/site-build-dav-sync-05 [git:build-dav-sync-05]$\n\n\n> \"common = NULL\" means merged_common_ancestors->tree is NULL in the caller.\n> Somebody is passing a bogus commit in \"ca\" (aka common ancestors) list\n> when calling merge_recursive(), or forgetting to parse them before calling\n> it.  In your debugger could you find out where it comes from and what it\n> has before this call into merge_trees() is made?  Specifically, what the\n> \"ca\" list at 0x7b3c00 contains, and how \"merged_common_ancestors\" at\n> 0x121e360 looks like. in this trace we see below:\n\nHere is the replay of the flow of execution from the first time we enter\nmerge_recursive().  The repository has been modified slightly so the\npointers are different this time but the segfault is still happening\n(I'll stop modifying the repository now ;-) .\n\nUpon entering merge_recursive() for the first time, ca is a two-item\nlist and both items have non-null trees:\n\nBreakpoint 1, merge_recursive (o=0x7fffffffd560, h1=0x793350,\nh2=0x7932c0, ca=0x7b4a40, result=0x7fffffffd5d8) at merge-recursive.c:1286\n(gdb) p *ca\n$1 = {item = 0x793db8, next = 0x7b4a20}\n(gdb) p *(ca->next)\n$2 = {item = 0x793aa0, next = 0x0}\n(gdb) p ca->item->tree\n$3 = (struct tree *) 0x77be10\n(gdb) p ca->next->item->tree\n$4 = (struct tree *) 0x77b488\n(gdb)\n\nThen on line 1303, the head of ca is popped off into\nmerged_common_ancestors:\n\nBreakpoint 2, merge_recursive (o=0x7fffffffd560, h1=0x793350,\nh2=0x7932c0, ca=0x7b4a20, result=0x7fffffffd5d8) at merge-recursive.c:1304\n(gdb) list\n1299\t\t\tfor (iter = ca; iter; iter = iter->next)\n1300\t\t\t\toutput_commit_title(o, iter->item);\n1301\t\t}\n1302\t\n1303\t\tmerged_common_ancestors = pop_commit(&ca);\n1304\t\tif (merged_common_ancestors == NULL) {\n1305\t\t\t/* if there is no common ancestor, make an empty tree */\n1306\t\t\tstruct tree *tree = xcalloc(1, sizeof(struct tree));\n1307\t\n1308\t\t\ttree->object.parsed = 1;\n(gdb) p merged_common_ancestors\n$5 = (struct commit *) 0x793db8\n(gdb) p ca\n$8 = (struct commit_list *) 0x7b4a20\n\nmerge_recursive() is then called recursively at line 1329 with a pointer\nto merged_common_ancestors passed as the \"result\" argument:\n\nBreakpoint 3, merge_recursive (o=0x7fffffffd560, h1=0x793350,\nh2=0x7932c0, ca=0x7b4a20, result=0x7fffffffd5d8) at merge-recursive.c:1329\n(gdb) list\n1324\t\t\tdiscard_cache();\n1325\t\t\tsaved_b1 = o->branch1;\n1326\t\t\tsaved_b2 = o->branch2;\n1327\t\t\to->branch1 = \"Temporary merge branch 1\";\n1328\t\t\to->branch2 = \"Temporary merge branch 2\";\n1329\t\t\tmerge_recursive(o, merged_common_ancestors, iter->item,\n1330\t\t\t\t\tNULL, &merged_common_ancestors);\n1331\t\t\to->branch1 = saved_b1;\n1332\t\t\to->branch2 = saved_b2;\n1333\t\t\to->call_depth--;\n(gdb)\n\nIn the second call to merged_common_ancestors(), result's pointee is\nreplaced by a commit with a null tree at line 1347:\n\nBreakpoint 4, merge_recursive (o=0x7fffffffd560, h1=0x793db8,\nh2=0x793aa0, ca=0x0, result=0x7fffffffd500) at merge-recursive.c:1347\n(gdb) n\n(gdb) p (*result)->tree\n$10 = (struct tree *) 0x0\n(gdb) list\n1343\t\tclean = merge_trees(o, h1->tree, h2->tree,\nmerged_common_ancestors->tree,\n1344\t\t\t\t    &mrtree);\n1345\t\n1346\t\tif (o->call_depth) {\n1347\t\t\t*result = make_virtual_commit(mrtree, \"merged tree\");\n1348\t\t\tcommit_list_insert(h1, &(*result)->parents);\n1349\t\t\tcommit_list_insert(h2, &(*result)->parents->next);\n1350\t\t}\n1351\t\tflush_output(o);\n1352\t\treturn clean;\n(gdb)\n\nmake_virtual_commit() is just setting its tree to mrtree:\n\nBreakpoint 5, make_virtual_commit (tree=0x0, comment=0x5016fc \"merged\ntree\") at merge-recursive.c:44\n(gdb) list\n39\t * A virtual commit has (const char *)commit->util set to the name.\n40\t */\n41\t\n42\tstatic struct commit *make_virtual_commit(struct tree *tree, const\nchar *comment)\n43\t{\n44\t\tstruct commit *commit = xcalloc(1, sizeof(struct commit));\n45\t\tcommit->tree = tree;\n46\t\tcommit->util = (void*)comment;\n47\t\t/* avoid warnings */\n48\t\tcommit->object.parsed = 1;\n(gdb)\n49\t\treturn commit;\n50\t}\n\nAt the beginning of merge_recursive(), the local mrtree appears to be\nset to some globally defined mrtree which is not null:\n\nBreakpoint 1, merge_recursive (o=0x7fffffffd560, h1=0x793db8,\nh2=0x793aa0, ca=0x0, result=0x7fffffffd500) at merge-recursive.c:1286\n(gdb) p mrtree\n$13 = (struct tree *) 0x7ffff732d0ac\n(gdb) list\n1281\t\tstruct commit_list *iter;\n1282\t\tstruct commit *merged_common_ancestors;\n1283\t\tstruct tree *mrtree = mrtree;\n1284\t\tint clean;\n1285\t\n1286\t\tif (show(o, 4)) {\n1287\t\t\toutput(o, 4, \"Merging:\");\n1288\t\t\toutput_commit_title(o, h1);\n1289\t\t\toutput_commit_title(o, h2);\n1290\t\t}\n(gdb)\n\nWhich leads me to believe the problem is in the call to merge_trees() at\nline 1343:\n\nBreakpoint 6, merge_recursive (o=0x7fffffffd560, h1=0x793db8,\nh2=0x793aa0, ca=0x0, result=0x7fffffffd500) at merge-recursive.c:1343\n(gdb) list\n1338\t\n1339\t\tdiscard_cache();\n1340\t\tif (!o->call_depth)\n1341\t\t\tread_cache();\n1342\t\n1343\t\tclean = merge_trees(o, h1->tree, h2->tree,\nmerged_common_ancestors->tree,\n1344\t\t\t\t    &mrtree);\n1345\t\n1346\t\tif (o->call_depth) {\n1347\t\t\t*result = make_virtual_commit(mrtree, \"merged tree\");\n(gdb)\n\nIn merge_trees(), mrtree is the argument **result.  It is at line 1255\nthat write_tree_from_memory nulls out the pointee of result:\n\nBreakpoint 7, merge_trees (o=0x7fffffffd560, head=0x77be10,\nmerge=0x77b488, common=0x77c0b8, result=0x7fffffffd478) at\nmerge-recursive.c:1255\n(gdb) p *result\n$16 = (struct tree *) 0x7ffff732d0ac\n(gdb) n\n(gdb) p *result\n$17 = (struct tree *) 0x0\n(gdb) list\n1252\t\t\tclean = 1;\n1253\t\n1254\t\tif (o->call_depth)\n1255\t\t\t*result = write_tree_from_memory(o);\n1256\t\n1257\t\treturn clean;\n1258\t}\n1259\t\n1260\tstatic struct commit_list *reverse_commit_list(struct commit_list\n*list)\n1261\t{\n(gdb)\n\nThen in write_tree_from_memory() we find the offending return NULL at\nline 210:\n\nBreakpoint 8, write_tree_from_memory (o=0x7fffffffd560) at\nmerge-recursive.c:210\n(gdb) list\n205\t\t\t\tstruct cache_entry *ce = active_cache[i];\n206\t\t\t\tif (ce_stage(ce))\n207\t\t\t\t\toutput(o, 0, \"%d %.*s\", ce_stage(ce),\n208\t\t\t\t\t       (int)ce_namelen(ce), ce->name);\n209\t\t\t}\n210\t\t\treturn NULL;\n211\t\t}\n212\t\n213\t\tif (!active_cache_tree)\n214\t\t\tactive_cache_tree = cache_tree();\n(gdb)\n\n\nLet me know if you need any more information.\n\nThanks,\nTim\n"},{"id":"132237","messageId":"7vtyugzabq.fsf@alter.siamese.dyndns.org","threadId":"22307","inReplyTo":"4B577C3F.7040608@brooklynpenguin.com","subject":"Re: git-merge segfault in 1.6.6 and master","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-01-20T22:21:45Z","receivedAt":"2010-01-20T22:21:45Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Tim Olsen <tim@brooklynpenguin.com> writes:\n\n> At the beginning of merge_recursive(), the local mrtree appears to be\n> set to some globally defined mrtree which is not null:\n\nNo; that \"assignment\" is just to squelch warning from gcc.  mrtree at that\npoint is uninitialized.\n\n> In merge_trees(), mrtree is the argument **result.  It is at line 1255\n> that write_tree_from_memory nulls out the pointee of result:\n> ...\n> Then in write_tree_from_memory() we find the offending return NULL at\n> line 210:\n>\n> Breakpoint 8, write_tree_from_memory (o=0x7fffffffd560) at\n> merge-recursive.c:210\n> (gdb) list\n> 205\t\t\t\tstruct cache_entry *ce = active_cache[i];\n> 206\t\t\t\tif (ce_stage(ce))\n> 207\t\t\t\t\toutput(o, 0, \"%d %.*s\", ce_stage(ce),\n> 208\t\t\t\t\t       (int)ce_namelen(ce), ce->name);\n> 209\t\t\t}\n> 210\t\t\treturn NULL;\n> 211\t\t}\n> 212\t\n> 213\t\tif (!active_cache_tree)\n> 214\t\t\tactive_cache_tree = cache_tree();\n> (gdb)\n\nAre you saying write_tree_from_memory() is returning NULL?  That probably\nmeans that in the recursive (i.e. the step that first merges multiple\ncommon ancestors into one) case the merge is getting conflicts.  Do you\nsee these \"There are unmerged index entries\" output?\n\nIn the recursive case (i.e. o->call_depth is non-zero), process_renames()\nand process_entry() are supposed to be forcing the conflicts resolved,\nrecording the contents with conflict markers if necessary, before the\ncontrol gets to that point, so it clearly is a bug very specific to the\nrecursive merge implementation.\n"},{"id":"132299","messageId":"20100121140057.GP12429@genesis.frugalware.org","threadId":"22307","inReplyTo":"4B577C3F.7040608@brooklynpenguin.com","subject":"Re: git-merge segfault in 1.6.6 and master","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2010-01-21T14:00:57Z","receivedAt":"2010-01-21T14:00:57Z","isPatch":false,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"On Wed, Jan 20, 2010 at 04:57:19PM -0500, Tim Olsen <tim@brooklynpenguin.com> wrote:\n> It appears that a segfault still happens with your patch applied, but\n> this time it is caught:\n> \n> tolsen@neurofunk:~/git/site-build-dav-sync-05 [git:build-dav-sync-05]$\n> git merge origin/deployed\n> error: merge-recursive died of signal 11\n> Merge with strategy recursive failed.\n> tolsen@neurofunk:~/git/site-build-dav-sync-05 [git:build-dav-sync-05]$\n> \n> \n> > \"common = NULL\" means merged_common_ancestors->tree is NULL in the caller.\n> > Somebody is passing a bogus commit in \"ca\" (aka common ancestors) list\n> > when calling merge_recursive(), or forgetting to parse them before calling\n> > it.  In your debugger could you find out where it comes from and what it\n> > has before this call into merge_trees() is made?  Specifically, what the\n> > \"ca\" list at 0x7b3c00 contains, and how \"merged_common_ancestors\" at\n> > 0x121e360 looks like. in this trace we see below:\n> \n> Here is the replay of the flow of execution from the first time we enter\n> merge_recursive().  The repository has been modified slightly so the\n> pointers are different this time but the segfault is still happening\n> (I'll stop modifying the repository now ;-) .\n\nTwo ideas to help debugging:\n\n- Can you try if this happens in a new repo as well? (If not, is the\n  repo public?) If yes, can you write a script that shows your problem?\n- Can you see if this happens with v1.6.0? If yes, can you bisect it?\n\nThanks.\n"},{"id":"132312","messageId":"4B5882BD.3090908@brooklynpenguin.com","threadId":"22307","inReplyTo":"7vtyugzabq.fsf@alter.siamese.dyndns.org","subject":"Re: git-merge segfault in 1.6.6 and master","fromName":"Tim Olsen","fromEmail":"tim@brooklynpenguin.com","sentAt":"2010-01-21T16:37:17Z","receivedAt":"2010-01-21T16:37:17Z","isPatch":false,"sender":{"key":"tim@brooklynpenguin.com","avatar":"https://gravatar.com/avatar/a468fd97b6433c4d22252ca75017d30a55046f5715e67b83e62b00a0833deb22?d=mp&s=160"},"body":"Junio C Hamano wrote:\n> Tim Olsen <tim@brooklynpenguin.com> writes:\n>> Breakpoint 8, write_tree_from_memory (o=0x7fffffffd560) at\n>> merge-recursive.c:210\n>> (gdb) list\n>> 205\t\t\t\tstruct cache_entry *ce = active_cache[i];\n>> 206\t\t\t\tif (ce_stage(ce))\n>> 207\t\t\t\t\toutput(o, 0, \"%d %.*s\", ce_stage(ce),\n>> 208\t\t\t\t\t       (int)ce_namelen(ce), ce->name);\n>> 209\t\t\t}\n>> 210\t\t\treturn NULL;\n>> 211\t\t}\n>> 212\t\n>> 213\t\tif (!active_cache_tree)\n>> 214\t\t\tactive_cache_tree = cache_tree();\n>> (gdb)\n> \n> Are you saying write_tree_from_memory() is returning NULL?  That probably\n> means that in the recursive (i.e. the step that first merges multiple\n> common ancestors into one) case the merge is getting conflicts.  Do you\n> see these \"There are unmerged index entries\" output?\n\nwrite_tree_from_memory() is returning NULL.  Stepping through the\nexecution in gdb shows it returning NULL at line 210.\n\nI do not see any output, however:\n\n$ git merge origin/deployed\nSegmentation fault\n$\n\n> In the recursive case (i.e. o->call_depth is non-zero), process_renames()\n> and process_entry() are supposed to be forcing the conflicts resolved,\n> recording the contents with conflict markers if necessary, before the\n> control gets to that point, so it clearly is a bug very specific to the\n> recursive merge implementation.\n\nSetting breakpoints on process_renames() and process_entry() shows that\nthey are being executed.  Is there anything I can gather from their\nexecution that would help you?\n\nTim\n"},{"id":"132323","messageId":"7viqavs4xc.fsf@alter.siamese.dyndns.org","threadId":"22307","inReplyTo":"4B5882BD.3090908@brooklynpenguin.com","subject":"Re: git-merge segfault in 1.6.6 and master","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-01-21T18:12:31Z","receivedAt":"2010-01-21T18:12:31Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Tim Olsen <tim@brooklynpenguin.com> writes:\n\n>> In the recursive case (i.e. o->call_depth is non-zero), process_renames()\n>> and process_entry() are supposed to be forcing the conflicts resolved,\n>> recording the contents with conflict markers if necessary, before the\n>> control gets to that point, so it clearly is a bug very specific to the\n>> recursive merge implementation.\n>\n> Setting breakpoints on process_renames() and process_entry() shows that\n> they are being executed.  Is there anything I can gather from their\n> execution that would help you?\n\nWhen they are called with non-zero o->call_depth, they are supposed to\ndrop all the index entries that they handle down to stage #0 (even if the\npath had contents level conflict).  For example, you see this bit in\nprocess_entry():\n\n\t} else if (a_sha && b_sha) {\n\t\t/* Case C: Added in both (check for same permissions) and */\n\t\t/* case D: Modified in both, but differently. */\n\t\tconst char *reason = \"content\";\n\t\t...\n\t\tmfi = merge_file(o, &one, &a, &b,\n\t\t\t\t o->branch1, o->branch2);\n\n\t\tclean_merge = mfi.clean;\n\t\tif (!mfi.clean) {\n\t\t\tif (S_ISGITLINK(mfi.mode))\n\t\t\t\treason = \"submodule\";\n\t\t\toutput(o, 1, \"CONFLICT (%s): Merge conflict in %s\",\n\t\t\t\t\treason, path);\n\t\t}\n\t\tupdate_file(o, mfi.clean, mfi.sha, mfi.mode, path);\n\t} ...\n\nand update_file() eventually calls update_file_flags() to make sure that\nthe content in mfi.sha is at the stage #0 of path when o->call_depth is\nnon-zero (or mfi.clean is true).  process_renames() and process_entry()\nare humongous functions that handle full of different cases, but all\ncodepaths must follow the rule not to leave non-stage #0 entries in the\nindex before merge_trees() function calls write_tree_from_memory().\n\nWe've fixed a similar bug in c94736a (merge-recursive: don't segfault\nwhile handling rename clashes, 2009-07-30) and I think there were similar\nbreakages we fixed over time in the same area, but the two functions being\nas huge as they are, I suspect you are hitting a codepath that hasn't been\nfixed.\n"},{"id":"132337","messageId":"4B58CD91.5000903@brooklynpenguin.com","threadId":"22307","inReplyTo":"20100121140057.GP12429@genesis.frugalware.org","subject":"Re: git-merge segfault in 1.6.6 and master","fromName":"Tim Olsen","fromEmail":"tim@brooklynpenguin.com","sentAt":"2010-01-21T21:56:33Z","receivedAt":"2010-01-21T21:56:33Z","isPatch":false,"sender":{"key":"tim@brooklynpenguin.com","avatar":"https://gravatar.com/avatar/a468fd97b6433c4d22252ca75017d30a55046f5715e67b83e62b00a0833deb22?d=mp&s=160"},"body":"Miklos Vajna wrote:\n> Two ideas to help debugging:\n> \n> - Can you try if this happens in a new repo as well? (If not, is the\n>   repo public?) If yes, can you write a script that shows your problem?\n\nThe problem still happens in any clone of the repository, but I have not\nattempted to reproduce the problem in a fresh repository.  I've put our\nrepository up at git://les.limebits.net/site (warning: the repo is about\n 364MB).  The following 3 commands will reproduce the problem:\n\ngit clone git://les.limebits.net/site\ncd site\ngit merge origin/deployed\n\nThe problem starts with commit 9079b71b6f.  I can merge its ancestors\nwith no problem into the default branch (build-dav-sync-05).  But commit\n9079b71b6f and its descendents cause a segfault when merging into\nbuild-dav-sync-05.\n\n> - Can you see if this happens with v1.6.0? If yes, can you bisect it?\n\nWith 1.6.0, the merge still fails but it doesn't outright segfault.\n\n$ git merge origin/deployed\nMerge with strategy recursive failed.\n$\n\nThe output appears to be from line 1098 of builtin-merge.c.  Bisecting\nfinds that the outright segfaulting starts with commit 18668f53:\n\ntolsen@neurofunk:~/git/git [git:NO BRANCH*]$ git bisect good\n18668f5319b079cce29e19817bc352b1413e0908 is first bad commit\ncommit 18668f5319b079cce29e19817bc352b1413e0908\nAuthor: Miklos Vajna <vmiklos@frugalware.org>\nDate:   Thu Aug 28 15:43:00 2008 +0200\n\n    builtin-merge: avoid run_command_v_opt() for recursive and subtree\n\n    The try_merge_strategy() function always ran the strategy in a separate\n    process, though this is not always necessary. The recursive and subtree\n    strategy can be called without a fork(). This patch adds a check, and\n    calls recursive in the same process without wasting resources.\n\n    Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n    Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>\n    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n\n:100644 100644 9ad9791068c9330f28413ac67315246989c8d96d\nb857cf6246978846e0c19895fd6f66266cf6a6f4 M      builtin-merge.c\ntolsen@neurofunk:~/git/git [git:NO BRANCH*]$\n\nThis leads me to believe the segfault may still be occurring in v1.6.0,\nbut in a separate process.\n\nTim\n\n> \n> Thanks.\n"},{"id":"132343","messageId":"7vhbqfj8fy.fsf@alter.siamese.dyndns.org","threadId":"22307","inReplyTo":"7viqavs4xc.fsf@alter.siamese.dyndns.org","subject":"Re: git-merge segfault in 1.6.6 and master","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-01-22T00:21:21Z","receivedAt":"2010-01-22T00:21:21Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> When they are called with non-zero o->call_depth, they are supposed to\n> drop all the index entries that they handle down to stage #0 (even if the\n> path had contents level conflict).  For example, you see this bit in\n> process_entry():\n>\n> \t} else if (a_sha && b_sha) {\n> \t\t/* Case C: Added in both (check for same permissions) and */\n> \t\t/* case D: Modified in both, but differently. */\n> \t\tconst char *reason = \"content\";\n> \t\t...\n> \t\tmfi = merge_file(o, &one, &a, &b,\n> \t\t\t\t o->branch1, o->branch2);\n>\n> \t\tclean_merge = mfi.clean;\n> \t\tif (!mfi.clean) {\n> \t\t\tif (S_ISGITLINK(mfi.mode))\n> \t\t\t\treason = \"submodule\";\n> \t\t\toutput(o, 1, \"CONFLICT (%s): Merge conflict in %s\",\n> \t\t\t\t\treason, path);\n> \t\t}\n> \t\tupdate_file(o, mfi.clean, mfi.sha, mfi.mode, path);\n> \t} ...\n>\n> and update_file() eventually calls update_file_flags() to make sure that\n> the content in mfi.sha is at the stage #0 of path when o->call_depth is\n> non-zero (or mfi.clean is true).  process_renames() and process_entry()\n> are humongous functions that handle full of different cases, but all\n> codepaths must follow the rule not to leave non-stage #0 entries in the\n> index before merge_trees() function calls write_tree_from_memory().\n>\n> We've fixed a similar bug in c94736a (merge-recursive: don't segfault\n> while handling rename clashes, 2009-07-30) and I think there were similar\n> breakages we fixed over time in the same area, but the two functions being\n> as huge as they are, I suspect you are hitting a codepath that hasn't been\n> fixed.\n\nAnd there are.\n\nFor example, this (drop it as t9999-junk.sh in t/ directory, go there and\nrun \"sh ./t-9999-junk.sh -v\") shows one codepath that makes merge-recursive\nfail to resolve the \"common ancestor\" merge.\n\n-- -- store in t/t9999-junk.sh and run -- --\n#!/bin/sh\n\ntest_description='common ancestor merge corner cases'\n\n. ./test-lib.sh\n\ntest_expect_success 'setup' '\n\tmkdir D &&\n\techo 1 >D/F1 &&\n\techo 2 >D/F2 &&\n\techo 3 >D/F3 &&\n\techo 4 >D/F4 &&\n\techo 5 >D/F5 &&\n\techo 6 >D/F6 &&\n\n\tgit add D &&\n\ttest_tick &&\n\tgit commit -m initial &&\n\tgit branch side &&\n\n\tgit checkout master &&\n\tgit mv D/F1 D/M1 &&\n\tgit rm D/F2 &&\n\techo 7 >>D/F3 &&\n\tgit mv D/F4 D/M4 &&\n\tgit rm D/F5 &&\n\tmkdir D/F5 &&\n\tgit mv D/F6 D/F5/M6 &&\n\tgit add -u &&\n\ttest_tick &&\n\tgit commit -m master &&\n\tgit tag A &&\n\n\tgit checkout side &&\n\tgit mv D/F1 D/S1 && # rename-rename conflict (dst)\n\techo 8 >>D/F2 && # remove-modify conflict\n\tgit mv D/F5 D/M4 && # rename-rename conflict (src)\n\tgit add -u &&\n\ttest_tick &&\n\tgit commit -m side &&\n\tgit tag B &&\n\n\tgit checkout side &&\n\ttest_tick &&\n\tgit merge -s ours master &&\n\tgit tag C &&\n\n\tgit checkout master &&\n\ttest_tick &&\n\tgit merge -s ours B &&\n\tgit tag D\n'\n\ntest_expect_success 'criss-cross' '\n\tgit checkout D &&\n\ttest_must_fail git merge side\n'\n\ntest_done\n-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --\n\nIt dies after showing this (D/F5/M6 is left unresolved in the forced\n\"common ancestor\" merge):\n\n  Merging:\n  f2f2f75 master\n  7994826 side\n  found 1 common ancestor(s):\n  f561e36 initial\n  CONFLICT (rename/rename): Rename \"D/F1\"->\"D/M1\" in branch \"Temporary merge branch 1\" rename \"D/F1\"->\"D/S1\" in \"Temporary merge branch 2\" (left unresolved)\n  CONFLICT (rename/add): Rename D/F4->D/M4 in Temporary merge branch 1. D/M4 added in Temporary merge branch 2\n  Adding merged D/M4\n  Skipped D/M4 (merged same as existing)\n  CONFLICT (rename/delete): Rename D/F5->D/M4 in Temporary merge branch 2 and deleted in Temporary merge branch 1\n  Skipped D/F5/M6 (merged same as existing)\n  CONFLICT (delete/modify): D/F2 deleted in Temporary merge branch 1 and modified in Temporary merge branch 2. Version Temporary merge branch 2 of D/F2 left in tree.\n  There are unmerged index entries:\n  2 D/F5/M6\n\n\nThe attached patch changes the behaviour to make this 9999-junk test pass,\nbut then it breaks t6036 (iow, the attached is _not_ a fix).\n\nAfter I stared at the code for more than two hours, I gave up trying to\ndiagnose this by myself.  People more familiar with the merge-recursive\nimplementation might be able to help figuring this out and may prove my\nsuspicion wrong, but I have a feeling that without a fairly big rewrite\nthe code is unsalvageable.\n\n-- >8 --\nNot a fix\n\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 1239647..132a6fc 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -1052,8 +1052,8 @@ static int process_renames(struct merge_options *o,\n \t\t\t\t\t\t\tupdate_stages(ren1_dst,\n \t\t\t\t\t\t\t\t      one, a, b, 1);\n \t\t\t\t\t}\n-\t\t\t\t\tupdate_file(o, mfi.clean, mfi.sha, mfi.mode, ren1_dst);\n \t\t\t\t}\n+\t\t\t\tupdate_file(o, mfi.clean, mfi.sha, mfi.mode, ren1_dst);\n \t\t\t}\n \t\t}\n \t}\n"},{"id":"132347","messageId":"7vaaw7j7mn.fsf@alter.siamese.dyndns.org","threadId":"22307","inReplyTo":"7vhbqfj8fy.fsf@alter.siamese.dyndns.org","subject":"Re: git-merge segfault in 1.6.6 and master","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-01-22T00:38:56Z","receivedAt":"2010-01-22T00:38:56Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> After I stared at the code for more than two hours, I gave up trying to\n> diagnose this by myself.  People more familiar with the merge-recursive\n> implementation might be able to help figuring this out and may prove my\n> suspicion wrong, but I have a feeling that without a fairly big rewrite\n> the code is unsalvageable.\n\nIn the meantime, I think applying this patch is the right thing to do.\n\n-- >8 --\nSubject: merge-recursive: do not return NULL only to cause segfault\n\nmerge-recursive calls write_tree_from_memory() to come up with a virtual\ntree, with possible conflict markers inside the blob contents, while\nmerging multiple common ancestors down.  It is a bug to call the function\nwith unmerged entries in the index, even if the merge to come up with the\ncommon ancestor resulted in conflicts.  Otherwise the result won't be\nexpressible as a tree object.\n\nWe _might_ want to suggest the user to set GIT_MERGE_VERBOSITY to 5 and\nre-run the merge in the message.  At least we will know which part of\nprocess_renames() or process_entry() functions is not correctly handling\nthe unmerged paths, and it might help us diagnosing the issue.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n merge-recursive.c |    8 ++++----\n 1 files changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 1239647..cb53b01 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -202,14 +202,14 @@ struct tree *write_tree_from_memory(struct merge_options *o)\n \n \tif (unmerged_cache()) {\n \t\tint i;\n-\t\toutput(o, 0, \"There are unmerged index entries:\");\n+\t\tfprintf(stderr, \"BUG: There are unmerged index entries:\\n\");\n \t\tfor (i = 0; i < active_nr; i++) {\n \t\t\tstruct cache_entry *ce = active_cache[i];\n \t\t\tif (ce_stage(ce))\n-\t\t\t\toutput(o, 0, \"%d %.*s\", ce_stage(ce),\n-\t\t\t\t       (int)ce_namelen(ce), ce->name);\n+\t\t\t\tfprintf(stderr, \"BUG: %d %.*s\", ce_stage(ce),\n+\t\t\t\t\t(int)ce_namelen(ce), ce->name);\n \t\t}\n-\t\treturn NULL;\n+\t\tdie(\"Bug in merge-recursive.c\");\n \t}\n \n \tif (!active_cache_tree)\n"}]}