From: Alexander Arkhipov Subject: bug/fix: segfault when diffing the root commit To: gameoftrees@openbsd.org Date: Tue, 6 Jun 2023 04:13:32 +0100 Hello, gameoftrees@, I noticed a bug in got, where typing `got -c file' causes a segfault. The issue is caused by the NULL pointer tree being accessed in find_entry_by_name() in lib/object.c. I fixed the problem the obvious way by immediately returning NULL if tree is NULL. Now, however, it instead outputs error messages like this: got: file: no such entry found in tree Is this OK, or should there be a more informative message? Either way, I don't think am familiar with the sources enough yet to make the fix much better. See the backtrace and the diff below. Alexander $ ~/bin/got diff -c 4027f31 Makefile Segmentation fault (core dumped) $ gdb ~/bin/got got.core GNU gdb 6.3 Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "amd64-unknown-openbsd7.3"... Core was generated by `got'. Program terminated with signal 11, Segmentation fault. Loaded symbols for /home/aa/bin/got Reading symbols from /usr/lib/libutil.so.16.0...done. Loaded symbols for /usr/lib/libutil.so.16.0 Reading symbols from /usr/lib/libz.so.7.0...done. Loaded symbols for /usr/lib/libz.so.7.0 Reading symbols from /usr/lib/libm.so.10.1...done. Loaded symbols for /usr/lib/libm.so.10.1 Reading symbols from /usr/lib/libc.so.97.0...done. Loaded symbols for /usr/lib/libc.so.97.0 Reading symbols from /usr/libexec/ld.so...Error while reading shared library symbols: Dwarf Error: wrong version in compilation unit header (is 4, should be 2) [in module /usr/libexec/ld.so] #0 find_entry_by_name (tree=0x0, name=0x148d5615f80 "Makefile", len=8) at /home/aa/ar/got/got/../lib/object.c:541 541 for (i = 0; i < tree->nentries; i++) { (gdb) bt #0 find_entry_by_name (tree=0x0, name=0x148d5615f80 "Makefile", len=8) at /home/aa/ar/got/got/../lib/object.c:541 #1 0x00000146aa825fae in got_object_tree_find_path (id=0x7b67ea463c10, mode=0x7b67ea463bdc, repo=0x1499d7a9460, tree=0x0, path=0x148d5615f80 "Makefile") at /home/aa/ar/got/got/../lib/object.c:589 #2 0x00000146aa81d4d5 in diff_paths (tree1=0x0, tree2=0x148d561f6a0, f1=0x14930cfb3d0, f2=0x14930cfb468, fd1=67, fd2=75, paths=0x7b67ea464158, repo=0x1499d7a9460, cb=0x146aa819160 , cb_arg=0x7b67ea463cc8) at /home/aa/ar/got/got/../lib/diff.c:1102 #3 0x00000146aa81bdff in diff_objects_as_trees (lines=0x0, nlines=0x0, f1=0x14930cfb3d0, f2=0x14930cfb468, fd1=67, fd2=75, id1=0x0, id2=0x148d561fe20, paths=0x7b67ea464158, label1=0x146aa7dbe8a "", label2=0x146aa7dbe8a "", diff_context=3, ignore_whitespace=0, force_text_diff=0, dsa=0x0, repo=0x1499d7a9460, outfile=0x14930cfb500, diff_algo=GOT_DIFF_ALGORITHM_PATIENCE) at /home/aa/ar/got/got/../lib/diff.c:1270 #4 0x00000146aa81c195 in got_diff_objects_as_commits (lines=0x0, nlines=0x0, f1=0x14930cfb3d0, f2=0x14930cfb468, fd1=67, fd2=75, id1=0x0, id2=0x148d55ff2a0, paths=0x7b67ea464158, diff_algo=GOT_DIFF_ALGORITHM_PATIENCE, diff_context=3, ignore_whitespace=0, force_text_diff=0, dsa=0x0, repo=0x1499d7a9460, outfile=0x14930cfb500) at /home/aa/ar/got/got/../lib/diff.c:1385 #5 0x00000146aa7f4a11 in cmd_diff (argc=1, argv=0x7b67ea464348) at /home/aa/ar/got/got/got.c:5483 #6 0x00000146aa7ed9f7 in main (argc=4, argv=0x7b67ea464330) at /home/aa/ar/got/got/got.c:261 Current language: auto; currently minimal (gdb) diff /home/aa/ar/got commit - 1f8d584437c06db990ac352cce06402c80b1f6a4 path + /home/aa/ar/got blob - 2e12a69bb09622ca93b1e6240e2f9d4b5f204a91 file + lib/object.c --- lib/object.c +++ lib/object.c @@ -537,6 +537,9 @@ find_entry_by_name(struct got_tree_object *tree, const { int i; + if (!tree) + return NULL; + /* Note that tree entries are sorted in strncmp() order. */ for (i = 0; i < tree->nentries; i++) { struct got_tree_entry *te = &tree->entries[i];