From: Stefan Sperling Subject: gotwebd segfault fix To: gameoftrees@openbsd.org Date: Fri, 9 Aug 2024 09:07:18 +0200 Lucas reported this gotwebd segfault on IRC: [[[ Program terminated with signal SIGSEGV, Segmentation fault. #0 0x00000d02d43236b1 in get_path_git_child (repo=0x0, basename=0xd02d42d508d "objects") at /home/got/code/got/gotwebd/../lib/repository.c:178 178 /home/got/code/got/gotwebd/../lib/repository.c: No such file or directory. (gdb) set max-value-size 131072 (gdb) bt full #0 0x00000d02d43236b1 in get_path_git_child (repo=0x0, basename=0xd02d42d508d "objects") at /home/got/code/got/gotwebd/../lib/repository.c:178 path_child = 0xd050000007f #1 0x00000d02d432366a in got_repo_get_path_objects (repo=0x0) at /home/got/code/got/gotwebd/../lib/repository.c:188 No locals. #2 0x00000d02d4327f94 in got_repo_match_object_id_prefix (id=0x7f289665fa90, id_str_prefix=0xd059220eba0 "8f6d9a6a62b3640c758a23e26cd567e2e44406e1", obj_type=1, repo=0x0) at /home/got/code/got/gotwebd/../lib/repository.c:1965 err = 0x0 path_objects = 0x0 object_dir = 0x0 len = 1622863644319942746 i = 3333 #3 0x00000d02d42f1338 in got_get_repo_commits (c=0xd057c2dd000, limit=1) at /home/got/code/got/gotwebd/got_operations.c:354 error = 0x0 id = 0x0 graph = 0x0 commit = 0x0 refs = {tqh_first = 0x0, tqh_last = 0x7f289665fa70} ref = 0x0 repo_commit = 0x0 srv = 0xd04f17be000 t = 0xd0545d98dc0 repo = 0x0 ]]] I cut the trace here because the last line shows the problem: t->repo is NULL. I believe the diff below might fix the issue. diff /home/stsp/src/got commit - 7e18255791187735b9e36951caa895974e4e9ba3 path + /home/stsp/src/got blob - ea44d67c0df8c731d5a45b797add4cbee60f171c file + gotwebd/gotweb.c --- gotwebd/gotweb.c +++ gotwebd/gotweb.c @@ -1142,12 +1142,15 @@ gotweb_load_got_path(struct repo_dir **rp, const char err: free(dir_test); if (dt != NULL && closedir(dt) == EOF && error == NULL) error = got_error_from_errno("closedir"); if (error && t->repo) { - got_repo_close(t->repo); - t->repo = NULL; + /* Some callers proceed doing work in this error case: */ + if (error->code != GOT_ERR_LONELY_PACKIDX) { + got_repo_close(t->repo); + t->repo = NULL; + } } return error; } static const struct got_error *