commit ebc8ef350dc7f15520ce1d1474510170bd055226 from: Stefan Sperling date: Wed Jun 25 08:23:52 2025 UTC fix infinite loop in got_pack_repaint_parent_commits() This can be observed during 'got send' or 'gotadmin pack/cleanup' in some cases. We would keep processing the same parent commits over and over. commit - c1696d0f5debe80ec8662a1e4dbcafe6856bf67e commit + ebc8ef350dc7f15520ce1d1474510170bd055226 blob - a431102c044792d034104d386d7ac6962d471951 blob + db7f080f5acaf39c23610da95bf5f1ab7771c2a3 --- lib/pack_create.c +++ lib/pack_create.c @@ -1053,14 +1053,19 @@ got_pack_repaint_parent_commits(struct got_object_id * struct got_object_idset *set, struct got_object_idset *skip, struct got_repository *repo) { - const struct got_error *err; + const struct got_error *err = NULL; struct got_object_id_queue ids; - struct got_object_qid *qid; - struct got_commit_object *commit; + struct got_object_qid *qid = NULL; + struct got_commit_object *commit = NULL; const struct got_object_id_queue *parents; + struct got_object_idset *traversed; STAILQ_INIT(&ids); + traversed = got_object_idset_alloc(); + if (traversed == NULL) + return got_error_from_errno("got_object_idset_alloc"); + err = got_object_open_as_commit(&commit, repo, commit_id); if (err) return err; @@ -1081,10 +1086,17 @@ got_pack_repaint_parent_commits(struct got_object_id * got_object_idset_contains(skip, &pid->id)) continue; + if (got_object_idset_contains(traversed, + &pid->id)) + continue; err = got_pack_queue_commit_id(&ids, &pid->id, color, repo); if (err) break; + err = got_object_idset_add(traversed, + &pid->id, NULL); + if (err) + goto done; } } got_object_commit_close(commit); @@ -1106,12 +1118,13 @@ got_pack_repaint_parent_commits(struct got_object_id * got_object_qid_free(qid); qid = NULL; } - +done: if (commit) got_object_commit_close(commit); if (qid) got_object_qid_free(qid); got_object_id_queue_free(&ids); + got_object_idset_free(traversed); return err; }