On Fri, Feb 14, 2020 at 01:22:11PM -0500, Jeff King wrote: > When we do a bitmap-aware revision traversal, we create an object_list > for each of the "haves" and "wants" tips. After creating the result > bitmaps these are no longer needed or used, but we never free the list > memory. > > Signed-off-by: Jeff King <peff@xxxxxxxx> > --- > object.c | 9 +++++++++ > object.h | 2 ++ > pack-bitmap.c | 5 +++++ > 3 files changed, 16 insertions(+) > > diff --git a/object.c b/object.c > index 142ef69399..4d11949b38 100644 > --- a/object.c > +++ b/object.c > @@ -307,6 +307,15 @@ int object_list_contains(struct object_list *list, struct object *obj) > return 0; > } > > +void object_list_free(struct object_list **list) > +{ > + while (*list) { > + struct object_list *p = *list; > + *list = p->next; > + free(p); > + } > +} Hmm. I was going to write a comment saying more-or-less, "I think I'm nitpicking here, but I'm not crazy about this as a 'while' loop". But, when I wrote this as a 'for' loop instead, I wrote a use-after-free, and then when I rid the code of that, it wasn't any more readable than the version above. > /* > * A zero-length string to which object_array_entry::name can be > * initialized without requiring a malloc/free. > diff --git a/object.h b/object.h > index 25f5ab3d54..2dbabfca0a 100644 > --- a/object.h > +++ b/object.h > @@ -151,6 +151,8 @@ struct object_list *object_list_insert(struct object *item, > > int object_list_contains(struct object_list *list, struct object *obj); > > +void object_list_free(struct object_list **list); > + > /* Object array handling .. */ > void add_object_array(struct object *obj, const char *name, struct object_array *array); > void add_object_array_with_path(struct object *obj, const char *name, struct object_array *array, unsigned mode, const char *path); > diff --git a/pack-bitmap.c b/pack-bitmap.c > index 9ca356ee29..6c06099dc7 100644 > --- a/pack-bitmap.c > +++ b/pack-bitmap.c > @@ -787,10 +787,15 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs) > bitmap_git->result = wants_bitmap; > bitmap_git->haves = haves_bitmap; > > + object_list_free(&wants); > + object_list_free(&haves); > + Makes sense. > return bitmap_git; > > cleanup: > free_bitmap_index(bitmap_git); > + object_list_free(&wants); > + object_list_free(&haves); Ditto. > return NULL; > } > > -- > 2.25.0.796.gcc29325708 Thanks, Taylor