{"thread":{"id":"42602","subject":"[patch] Out of bounds read in git apply on malformed input in gitdiff_verify_name()","startedAt":"2016-06-16T06:55:52Z","lastAt":"2016-06-16T06:55:52Z","messageCount":1,"participants":["Hanno Böck"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"289203","messageId":"20160614125218.18e08566@pc1","threadId":"42602","inReplyTo":null,"subject":"[patch] Out of bounds read in git apply on malformed input in gitdiff_verify_name()","fromName":"Hanno Böck","fromEmail":"hanno@hboeck.de","sentAt":"2016-06-14T10:52:18Z","receivedAt":"2016-06-16T06:55:52Z","isPatch":true,"sender":{"key":"hanno@hboeck.de","avatar":"https://gravatar.com/avatar/79b34ab31390dbd2ca7a8550994c8b6e1ad637e77071a3a25e76d7810236369d?d=mp&s=160"},"body":"Hi,\n\nThe attached sample file will cause an out of bounds heap read in the\nfunction gitdiff_verify_name() when passed to git apply.\n\nTo reproduce:\n* Build git with address sanitizer (-fsanitize=address in cflags)\n* git apply --check [path_to_file]\n\nI have pasted the full address sanitizer error trace below.\n\nThe code where this happens is here (builtin/apply.c):\n                if (!another || memcmp(another, orig_name, len + 1))\n\nThe problem seems to be that there is no guarantee that another and\norig_name have the same length, len is set to strlen(orig_name) a few\nlines earlier. Thus if orig_name is more than 1 byte shorter than\nanother it causes an invalid memory read.\n\nChanging memcmp to strncmp should fix this, patch attached.\n\nFound with the help of american fuzzy lop and address sanitizer.\n\n\n==7717==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000ed30 at pc 0x41d3ab bp 0x7ffd00ad61d0 sp 0x7ffd00ad61c0\nREAD of size 3 at 0x60200000ed30 thread T0\n    #0 0x41d3aa in gitdiff_verify_name builtin/apply.c:940\n    #1 0x41d687 in gitdiff_oldname builtin/apply.c:956\n    #2 0x41f387 in parse_git_header builtin/apply.c:1309\n    #3 0x42014b in find_header builtin/apply.c:1475\n    #4 0x422bc5 in parse_chunk builtin/apply.c:1988\n    #5 0x432c24 in apply_patch builtin/apply.c:4373\n    #6 0x433df8 in cmd_apply builtin/apply.c:4626\n    #7 0x407dcd in run_builtin /f/git/plain/git-2.9.0/git.c:352\n    #8 0x40818c in handle_builtin /f/git/plain/git-2.9.0/git.c:539\n    #9 0x4084db in run_argv /f/git/plain/git-2.9.0/git.c:593\n    #10 0x408934 in main /f/git/plain/git-2.9.0/git.c:698\n    #11 0x7fddbf96c78f in __libc_start_main (/lib64/libc.so.6+0x2078f)\n    #12 0x405308 in _start (/f/git/plain/git-2.9.0/git+0x405308)\n\n0x60200000ed32 is located 0 bytes to the right of 2-byte region [0x60200000ed30,0x60200000ed32)\nallocated by thread T0 here:\n    #0 0x7fddc07b9707 in malloc (/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/libasan.so.1+0x57707)\n    #1 0x790768 in do_xmalloc /f/git/plain/git-2.9.0/wrapper.c:59\n    #2 0x79089e in do_xmallocz /f/git/plain/git-2.9.0/wrapper.c:99\n    #3 0x79090f in xmallocz /f/git/plain/git-2.9.0/wrapper.c:107\n    #4 0x79094c in xmemdupz /f/git/plain/git-2.9.0/wrapper.c:123\n    #5 0x41c1f7 in find_name_common builtin/apply.c:704\n    #6 0x41c29b in find_name builtin/apply.c:715\n    #7 0x41d31b in gitdiff_verify_name builtin/apply.c:939\n    #8 0x41d687 in gitdiff_oldname builtin/apply.c:956\n    #9 0x41f387 in parse_git_header builtin/apply.c:1309\n    #10 0x42014b in find_header builtin/apply.c:1475\n    #11 0x422bc5 in parse_chunk builtin/apply.c:1988\n    #12 0x432c24 in apply_patch builtin/apply.c:4373\n    #13 0x433df8 in cmd_apply builtin/apply.c:4626\n    #14 0x407dcd in run_builtin /f/git/plain/git-2.9.0/git.c:352\n    #15 0x40818c in handle_builtin /f/git/plain/git-2.9.0/git.c:539\n    #16 0x4084db in run_argv /f/git/plain/git-2.9.0/git.c:593\n    #17 0x408934 in main /f/git/plain/git-2.9.0/git.c:698\n    #18 0x7fddbf96c78f in __libc_start_main (/lib64/libc.so.6+0x2078f)\n\nSUMMARY: AddressSanitizer: heap-buffer-overflow builtin/apply.c:940 gitdiff_verify_name\nShadow bytes around the buggy address:\n  0x0c047fff9d50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa\n  0x0c047fff9d60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa\n  0x0c047fff9d70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa\n  0x0c047fff9d80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa\n  0x0c047fff9d90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa\n=>0x0c047fff9da0: fa fa fa fa fa fa[02]fa fa fa 03 fa fa fa fd fd\n  0x0c047fff9db0: fa fa 03 fa fa fa 00 02 fa fa fd fd fa fa 00 00\n  0x0c047fff9dc0: fa fa 04 fa fa fa 00 03 fa fa fd fd fa fa 00 00\n  0x0c047fff9dd0: fa fa 01 fa fa fa 00 06 fa fa 05 fa fa fa 00 04\n  0x0c047fff9de0: fa fa 04 fa fa fa 06 fa fa fa 00 04 fa fa 00 04\n  0x0c047fff9df0: fa fa 00 04 fa fa 00 04 fa fa fd fa fa fa 02 fa\nShadow byte legend (one shadow byte represents 8 application bytes):\n  Addressable:           00\n  Partially addressable: 01 02 03 04 05 06 07 \n  Heap left redzone:       fa\n  Heap right redzone:      fb\n  Freed heap region:       fd\n  Stack left redzone:      f1\n  Stack mid redzone:       f2\n  Stack right redzone:     f3\n  Stack partial redzone:   f4\n  Stack after return:      f5\n  Stack use after scope:   f8\n  Global redzone:          f9\n  Global init order:       f6\n  Poisoned by user:        f7\n  Contiguous container OOB:fc\n  ASan internal:           fe\n==7717==ABORTING\n\n-- \nHanno Böck\nhttps://hboeck.de/\n\nmail/jabber: hanno@hboeck.de\nGPG: BBB51E42\n\n\ndiff -Naur git-2.9.0/builtin/apply.c git-2.9.0-1/builtin/apply.c\n--- git-2.9.0/builtin/apply.c\t2016-06-13 21:07:49.000000000 +0200\n+++ git-2.9.0-1/builtin/apply.c\t2016-06-14 11:38:19.940588382 +0200\n@@ -937,7 +937,7 @@\n \t\t\tdie(_(\"git apply: bad git-diff - expected /dev/null, got %s on line %d\"),\n \t\t\t    orig_name, linenr);\n \t\tanother = find_name(line, NULL, p_value, TERM_TAB);\n-\t\tif (!another || memcmp(another, orig_name, len + 1))\n+\t\tif (!another || strncmp(another, orig_name, len + 1))\n \t\t\tdie((side == DIFF_NEW_NAME) ?\n \t\t\t    _(\"git apply: bad git-diff - inconsistent new filename on line %d\") :\n \t\t\t    _(\"git apply: bad git-diff - inconsistent old filename on line %d\"), linenr);\n\n\ndiff --git \n--- /00\n--- /0\n"}]}