"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Alexander Arkhipov <aa@manpager.net>
Subject:
bug/fix: segfault when diffing the root commit
To:
gameoftrees@openbsd.org
Date:
Tue, 6 Jun 2023 04:13:32 +0100

Download raw body.

Thread
Hello, gameoftrees@,

I noticed a bug in got, where typing `got -c <root commit> 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 <got_diff_blob_output_unidiff>, 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];