Show 51 quoted lines
>
> On Sun, Aug 16, 2020 at 06:59:10AM +0000, Elijah Newren via GitGitGadget wrote:
>
> > From: Elijah Newren <newren@gmail.com>
> >
> > The calling convention for the dir API is supposed to end with a call to
> > clear_directory() to free up no longer needed memory. However,
> > clear_directory() didn't free dir->entries or dir->ignored. I believe
> > this was oversight, but a number of callers noticed memory leaks and
> > started free'ing these, but often somewhat haphazardly (sometimes
> > freeing the entries in the arrays, and sometimes only free'ing the
> > arrays themselves). This suggests the callers weren't trying to make
> > sure any possible memory used might be free'd, but just the memory they
> > noticed their usecase definitely had allocated. This also caused the
> > extra memory deallocations to be duplicated in many places.
> >
> > Fix this mess by moving all the duplicated free'ing logic into
> > clear_directory().
>
> Makes sense. I don't know the dir.c code very well, so my worry would be
> that some caller really wanted the other fields left untouched. But
> looking over the callers, it seems they're all clearing it before the
> struct goes out of scope. It's possible that they could have created
> other pointer references, but it seems unlikely (and I'd argue they
> should stop doing that and make their own copies of the data). E.g.,
> wt_status_collect_untracked() sticks names into a string_list, but it
> sets strdup_strings to make its own copy, so it's good.
>
> > @@ -3034,6 +3031,13 @@ void clear_directory(struct dir_struct *dir)
> > free(group->pl);
> > }
> >
> > + for (i = 0; i < dir->ignored_nr; i++)
> > + free(dir->ignored[i]);
> > + for (i = 0; i < dir->nr; i++)
> > + free(dir->entries[i]);
> > + free(dir->ignored);
> > + free(dir->entries);
> > +
> > stk = dir->exclude_stack;
> > while (stk) {
> > struct exclude_stack *prev = stk->prev;
>
> In most of our "clear" functions, the struct is ready for use again
> (i.e., fields are set back to the initialized state). I don't think any
> caller cares at this point, but it may be worth doing while we are here
> as a least-surprise thing. That would mean setting these pointers to
> NULL, and probably a few others that you aren't touching here.
>
> Perhaps even easier would be to add a dir_init() call at the end after
> your next patch adds that function.