]> git.ipfire.org Git - thirdparty/git.git/commitdiff
negotiator/skipping: avoid stack overflow
authorJonathan Tan <jonathantanmy@google.com>
Tue, 25 Oct 2022 23:29:34 +0000 (16:29 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 26 Oct 2022 00:14:40 +0000 (17:14 -0700)
mark_common() in negotiator/skipping.c may overflow the stack due to
recursive function calls. Avoid this by instead recursing using a
heap-allocated data structure.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
negotiator/skipping.c

index c4398f5ae15d320b5f7167105a08d94fe6bbf4fa..0f5ac48e87608ee9fee69efb94b51d985b60c707 100644 (file)
@@ -86,21 +86,26 @@ static int clear_marks(const char *refname, const struct object_id *oid,
 /*
  * Mark this SEEN commit and all its SEEN ancestors as COMMON.
  */
-static void mark_common(struct data *data, struct commit *c)
+static void mark_common(struct data *data, struct commit *seen_commit)
 {
-       struct commit_list *p;
+       struct prio_queue queue = { NULL };
+       struct commit *c;
 
-       if (c->object.flags & COMMON)
-               return;
-       c->object.flags |= COMMON;
-       if (!(c->object.flags & POPPED))
-               data->non_common_revs--;
+       prio_queue_put(&queue, seen_commit);
+       while ((c = prio_queue_get(&queue))) {
+               struct commit_list *p;
+               if (c->object.flags & COMMON)
+                       return;
+               c->object.flags |= COMMON;
+               if (!(c->object.flags & POPPED))
+                       data->non_common_revs--;
 
-       if (!c->object.parsed)
-               return;
-       for (p = c->parents; p; p = p->next) {
-               if (p->item->object.flags & SEEN)
-                       mark_common(data, p->item);
+               if (!c->object.parsed)
+                       return;
+               for (p = c->parents; p; p = p->next) {
+                       if (p->item->object.flags & SEEN)
+                               prio_queue_put(&queue, p->item);
+               }
        }
 }