8000 Fix memory leaks by csware · Pull Request #6748 · libgit2/libgit2 · GitHub
[go: up one dir, main page]

Skip to content

Fix memory leaks #6748

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 28, 2024
Merged

Fix memory leaks #6748

merged 1 commit into from
Feb 28, 2024

Conversation

csware
Copy link
Contributor
@csware csware commented Feb 24, 2024

fixes #6746

Signed-off-by: Sven Strickroth <email@cs-ware.de>
@@ -3246,14 +3246,18 @@ int git_repository_set_workdir(
if (git_fs_path_prettify_dir(&path, workdir, NULL) < 0)
return -1;

if (repo->workdir && strcmp(repo->workdir, path.ptr) == 0)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wanted to propose ad additional optimisation: I don't see that much sense in allocating a string and potentially to deallocate it. I think we should do it if and only if workdir != repo->workdir (namely we should call git_fs_path_prettify_dir after checking that we really have a new different working dir).

if (!repo->workdir || strcmp(repo->workdir, wordir) == 0)
  return 0;
if (git_fs_path_prettify_dir(&path, workdir, NULL) < 0)
  return -1;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not logically equivalent, though. Currently, we're comparing the canonicalized input against the existing workdir (which is also already canonicalized). If we do the comparison before the canonicalization (prettify), then if repo->workdir = "/path/to/current/workdir/" and set_workdir was called with /path/to/current/workdir, then the strcmp would not be equivalent, and we'd go through the whole "change the current workdir" logic incorrectly.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see! Sorry again (I didn't check too much in detail what git_fs_path_prettify_dir was really doing).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries at all - I appreciate the extra set of eyes!

@@ -3246,14 +3246,18 @@ int git_repository_set_workdir(
if (git_fs_path_prettify_dir(&path, workdir, NULL) < 0)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have one comment about this call as well. When checking its implementation there are 2 paths where we do not deallocate the buffer if the function fails, while there's one where we correctly deallocate path.

Here where we do not deallocate in case of error:

return -1;

return git_str_sets(path_out, buf);

I apologise if I am wrong (not too familiar with libgit2 codebase), but I would assume a function does clean up in case of error for all paths, and because of this a fix like this:

if (git_fs_path_prettify_dir(&path, workdir, NULL) < 0) {
    git_str_dispose(&path);
    return -1;
}

won't work because we might hit a double-free problem.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this is safe as it stands — there's a couple of things worth point out:

  1. The library's philosophy (as of today) is that we will accept a few memory leaks during an out-of-memory scenario, on the assumption that we're about to exit. This admittedly seems to assume a lot, and I think that we should revisit these assumptions, but today, you will see a lot of instances of things like (pseudo-code):

    if ((ptr1 = malloc(1024)) == NULL ||
        (ptr2 = malloc(1024)) == NULL)
        return NULL;
    

    This would obviously leak ptr1's memory in the case that the ptr2 allocation failed, but this is the design as it exists today. The thinking is that if you can't allocate a few kilobytes, we're well and truly screwed. (Note, however, that we should not gratuitously leak memory on large allocation failures.)

  2. Here, though, we're using a git_str, which should be self-contained. If any of the git_str_... functions fail, the git_str itself should probably not be mutated. For example, given: git_str_clear(&foo); git_str_puts(&foo, "bar"); git_str_puts(&foo, twenty_gigs_of_content); if that huge append at the end fails, then the git_str should still contain bar. So I think that trying to do any cleanup in fs_path_prettify_dir would be incorrect.

  3. You can safely call git_str_dispose() multiple times, a git_str won't double-free.

@ethomson
Copy link
Member

Thanks for the fix!

@ethomson ethomson merged commit 4ab9c40 into libgit2:main Feb 28, 2024
@csware csware deleted the fix-memleaks branch March 8, 2024 09:01
@ethomson ethomson added the bug label Mar 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Memory leak in git_repository_set_workdir(for unhappy paths and when resetting the same working dir)
3 participants
0